From 19f32e8b95817bcc2ef0a73bbcb4be16e101c989 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 02 Dec 2013 11:07:17 +0000
Subject: [PATCH] OpenDJ 3 : config framework

---
 opendj-admin/src/main/java/org/opends/server/admin/client/spi/Driver.java | 1328 ++++++++++++++++++++++++++-------------------------------
 1 files changed, 612 insertions(+), 716 deletions(-)

diff --git a/opendj-admin/src/main/java/org/opends/server/admin/client/spi/Driver.java b/opendj-admin/src/main/java/org/opends/server/admin/client/spi/Driver.java
index 99621ec..f88c255 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/client/spi/Driver.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/client/spi/Driver.java
@@ -27,8 +27,6 @@
 
 package org.opends.server.admin.client.spi;
 
-
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -36,7 +34,8 @@
 import java.util.List;
 import java.util.SortedSet;
 
-import org.opends.messages.Message;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.admin.client.RootCfgClient;
 import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
 import org.opends.server.admin.AliasDefaultBehaviorProvider;
@@ -70,740 +69,637 @@
 import org.opends.server.admin.client.ManagementContext;
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.client.OperationRejectedException.OperationType;
-import org.opends.server.admin.std.client.RootCfgClient;
-
-
 
 /**
- * An abstract management connection context driver which should form
- * the basis of driver implementations.
+ * An abstract management connection context driver which should form the basis
+ * of driver implementations.
  */
 public abstract class Driver {
 
-  /**
-   * A default behavior visitor used for retrieving the default values
-   * of a property.
-   *
-   * @param <T>
-   *          The type of the property.
-   */
-  private class DefaultValueFinder<T> implements
-      DefaultBehaviorProviderVisitor<T, Collection<T>, Void> {
-
-    // Any exception that occurred whilst retrieving inherited default
-    // values.
-    private DefaultBehaviorException exception = null;
-
-    // The path of the managed object containing the first property.
-    private final ManagedObjectPath<?, ?> firstPath;
-
-    // Indicates whether the managed object has been created yet.
-    private final boolean isCreate;
-
-    // The path of the managed object containing the next property.
-    private ManagedObjectPath<?, ?> nextPath = null;
-
-    // The next property whose default values were required.
-    private PropertyDefinition<T> nextProperty = null;
-
-
-
-    // Private constructor.
-    private DefaultValueFinder(ManagedObjectPath<?, ?> p, boolean isCreate) {
-      this.firstPath = p;
-      this.isCreate = isCreate;
-    }
-
-
-
     /**
-     * {@inheritDoc}
+     * A default behavior visitor used for retrieving the default values of a
+     * property.
+     *
+     * @param <T>
+     *            The type of the property.
      */
-    public Collection<T> visitAbsoluteInherited(
-        AbsoluteInheritedDefaultBehaviorProvider<T> d, Void p) {
-      try {
-        return getInheritedProperty(d.getManagedObjectPath(), d
-            .getManagedObjectDefinition(), d.getPropertyName());
-      } catch (DefaultBehaviorException e) {
-        exception = e;
-        return Collections.emptySet();
-      }
-    }
+    private class DefaultValueFinder<T> implements DefaultBehaviorProviderVisitor<T, Collection<T>, Void> {
 
+        // Any exception that occurred whilst retrieving inherited default
+        // values.
+        private DefaultBehaviorException exception = null;
 
+        // The path of the managed object containing the first property.
+        private final ManagedObjectPath<?, ?> firstPath;
 
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d, Void p) {
-      return Collections.emptySet();
-    }
+        // Indicates whether the managed object has been created yet.
+        private final boolean isCreate;
 
+        // The path of the managed object containing the next property.
+        private ManagedObjectPath<?, ?> nextPath = null;
 
+        // The next property whose default values were required.
+        private PropertyDefinition<T> nextProperty = null;
 
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
-        Void p) {
-      Collection<String> stringValues = d.getDefaultValues();
-      List<T> values = new ArrayList<T>(stringValues.size());
-
-      for (String stringValue : stringValues) {
-        try {
-          values.add(nextProperty.decodeValue(stringValue));
-        } catch (IllegalPropertyValueStringException e) {
-          exception = new DefaultBehaviorException(nextProperty, e);
-          break;
-        }
-      }
-
-      return values;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<T> visitRelativeInherited(
-        RelativeInheritedDefaultBehaviorProvider<T> d, Void p) {
-      try {
-        return getInheritedProperty(d.getManagedObjectPath(nextPath), d
-            .getManagedObjectDefinition(), d.getPropertyName());
-      } catch (DefaultBehaviorException e) {
-        exception = e;
-        return Collections.emptySet();
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
-        Void p) {
-      return Collections.emptySet();
-    }
-
-
-
-    // Find the default values for the next path/property.
-    private Collection<T> find(ManagedObjectPath<?, ?> p,
-        PropertyDefinition<T> pd) throws DefaultBehaviorException {
-      this.nextPath = p;
-      this.nextProperty = pd;
-
-      Collection<T> values = nextProperty.getDefaultBehaviorProvider().accept(
-          this, null);
-
-      if (exception != null) {
-        throw exception;
-      }
-
-      if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
-        throw new DefaultBehaviorException(pd,
-            new PropertyIsSingleValuedException(pd));
-      }
-
-      return values;
-    }
-
-
-
-    // Get an inherited property value.
-    @SuppressWarnings("unchecked")
-    private Collection<T> getInheritedProperty(ManagedObjectPath target,
-        AbstractManagedObjectDefinition<?, ?> d, String propertyName)
-        throws DefaultBehaviorException {
-      // First check that the requested type of managed object
-      // corresponds to the path.
-      AbstractManagedObjectDefinition<?, ?> supr = target
-          .getManagedObjectDefinition();
-      if (!supr.isParentOf(d)) {
-        throw new DefaultBehaviorException(
-            nextProperty, new DefinitionDecodingException(supr,
-                Reason.WRONG_TYPE_INFORMATION));
-      }
-
-      // Save the current property in case of recursion.
-      PropertyDefinition<T> pd1 = nextProperty;
-
-      try {
-        // Determine the requested property definition.
-        PropertyDefinition<T> pd2;
-        try {
-          // FIXME: we use the definition taken from the default
-          // behavior here when we should really use the exact
-          // definition of the component being created.
-          PropertyDefinition<?> pdTmp = d.getPropertyDefinition(propertyName);
-          pd2 = pd1.getClass().cast(pdTmp);
-        } catch (IllegalArgumentException e) {
-          throw new PropertyNotFoundException(propertyName);
-        } catch (ClassCastException e) {
-          // FIXME: would be nice to throw a better exception here.
-          throw new PropertyNotFoundException(propertyName);
+        // Private constructor.
+        private DefaultValueFinder(ManagedObjectPath<?, ?> p, boolean isCreate) {
+            this.firstPath = p;
+            this.isCreate = isCreate;
         }
 
-        // If the path relates to the current managed object and the
-        // managed object is in the process of being created it won't
-        // exist, so we should just use the default values of the
-        // referenced property.
-        if (isCreate && firstPath.equals(target)) {
-          // Recursively retrieve this property's default values.
-          Collection<T> tmp = find(target, pd2);
-          Collection<T> values = new ArrayList<T>(tmp.size());
-          for (T value : tmp) {
-            pd1.validateValue(value);
-            values.add(value);
-          }
-          return values;
-        } else {
-          // FIXME: issue 2481 - this is broken if the referenced property
-          // inherits its defaults from the newly created managed object.
-          return getPropertyValues(target, pd2);
+        /**
+         * {@inheritDoc}
+         */
+        public Collection<T> visitAbsoluteInherited(AbsoluteInheritedDefaultBehaviorProvider<T> d, Void p) {
+            try {
+                return getInheritedProperty(d.getManagedObjectPath(), d.getManagedObjectDefinition(),
+                        d.getPropertyName());
+            } catch (DefaultBehaviorException e) {
+                exception = e;
+                return Collections.emptySet();
+            }
         }
-      } catch (DefaultBehaviorException e) {
-        // Wrap any errors due to recursion.
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (DefinitionDecodingException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (PropertyNotFoundException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (AuthorizationException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (ManagedObjectNotFoundException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (CommunicationException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      } catch (PropertyException e) {
-        throw new DefaultBehaviorException(pd1, e);
-      }
-    }
-  };
 
-
-
-  /**
-   * Creates a new abstract management context.
-   */
-  protected Driver() {
-    // No implementation required.
-  }
-
-
-
-  /**
-   * Closes any context associated with this management context
-   * driver.
-   */
-  public void close() {
-    // do nothing by default
-  }
-
-
-
-  /**
-   * Deletes the named instantiable child managed object from the
-   * named parent managed object.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param parent
-   *          The path of the parent managed object.
-   * @param rd
-   *          The instantiable relation definition.
-   * @param name
-   *          The name of the child managed object to be removed.
-   * @return Returns <code>true</code> if the named instantiable
-   *         child managed object was found, or <code>false</code>
-   *         if it was not found.
-   * @throws IllegalArgumentException
-   *           If the relation definition is not associated with the
-   *           parent managed object's definition.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be removed due to some
-   *           client-side or server-side constraint which cannot be
-   *           satisfied (for example, if it is referenced by another
-   *           managed object).
-   * @throws AuthorizationException
-   *           If the server refuses to remove the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  boolean deleteManagedObject(
-      ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd,
-      String name) throws IllegalArgumentException,
-      ManagedObjectNotFoundException, OperationRejectedException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(parent, rd);
-    ManagedObjectPath<?, ?> child = parent.child(rd, name);
-    return doDeleteManagedObject(child);
-  }
-
-
-
-  /**
-   * Deletes the optional child managed object from the named parent
-   * managed object.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param parent
-   *          The path of the parent managed object.
-   * @param rd
-   *          The optional relation definition.
-   * @return Returns <code>true</code> if the optional child managed
-   *         object was found, or <code>false</code> if it was not
-   *         found.
-   * @throws IllegalArgumentException
-   *           If the relation definition is not associated with the
-   *           parent managed object's definition.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be removed due to some
-   *           client-side or server-side constraint which cannot be
-   *           satisfied (for example, if it is referenced by another
-   *           managed object).
-   * @throws AuthorizationException
-   *           If the server refuses to remove the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  boolean deleteManagedObject(
-      ManagedObjectPath<?, ?> parent, OptionalRelationDefinition<C, S> rd)
-      throws IllegalArgumentException, ManagedObjectNotFoundException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException {
-    validateRelationDefinition(parent, rd);
-    ManagedObjectPath<?, ?> child = parent.child(rd);
-    return doDeleteManagedObject(child);
-  }
-
-
-
-  /**
-   * Deletes the named instantiable child managed object from the
-   * named parent managed object.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param parent
-   *          The path of the parent managed object.
-   * @param rd
-   *          The instantiable relation definition.
-   * @param name
-   *          The name of the child managed object to be removed.
-   * @return Returns <code>true</code> if the named instantiable
-   *         child managed object was found, or <code>false</code>
-   *         if it was not found.
-   * @throws IllegalArgumentException
-   *           If the relation definition is not associated with the
-   *           parent managed object's definition.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be removed due to some
-   *           client-side or server-side constraint which cannot be
-   *           satisfied (for example, if it is referenced by another
-   *           managed object).
-   * @throws AuthorizationException
-   *           If the server refuses to remove the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  boolean deleteManagedObject(
-      ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd,
-      String name) throws IllegalArgumentException,
-      ManagedObjectNotFoundException, OperationRejectedException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(parent, rd);
-    ManagedObjectPath<?, ?> child = parent.child(rd, name);
-    return doDeleteManagedObject(child);
-  }
-
-
-
-  /**
-   * Gets the named managed object. The path is guaranteed to be
-   * non-empty, so implementations do not need to worry about handling
-   * this special case.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          path definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          path definition refers to.
-   * @param path
-   *          The non-empty path of the managed object.
-   * @return Returns the named managed object.
-   * @throws DefinitionDecodingException
-   *           If the managed object was found but its type could not
-   *           be determined.
-   * @throws ManagedObjectDecodingException
-   *           If the managed object was found but one or more of its
-   *           properties could not be decoded.
-   * @throws ManagedObjectNotFoundException
-   *           If the requested managed object could not be found on
-   *           the server.
-   * @throws AuthorizationException
-   *           If the server refuses to retrieve the managed object
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public abstract <C extends ConfigurationClient, S extends Configuration>
-  ManagedObject<? extends C> getManagedObject(
-      ManagedObjectPath<C, S> path) throws DefinitionDecodingException,
-      ManagedObjectDecodingException, ManagedObjectNotFoundException,
-      AuthorizationException, CommunicationException;
-
-
-
-  /**
-   * Gets the effective values of a property in the named managed
-   * object.
-   * <p>
-   * Implementations MUST NOT not use
-   * {@link #getManagedObject(ManagedObjectPath)} to read the
-   * referenced managed object in its entirety. Specifically,
-   * implementations MUST only attempt to resolve the default values
-   * for the requested property and its dependencies (if it uses
-   * inherited defaults). This is to avoid infinite recursion where a
-   * managed object contains a property which inherits default values
-   * from another property in the same managed object.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          path definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          path definition refers to.
-   * @param <PD>
-   *          The type of the property to be retrieved.
-   * @param path
-   *          The path of the managed object containing the property.
-   * @param pd
-   *          The property to be retrieved.
-   * @return Returns the property's effective values, or an empty set
-   *         if there are no values defined.
-   * @throws IllegalArgumentException
-   *           If the property definition is not associated with the
-   *           referenced managed object's definition.
-   * @throws DefinitionDecodingException
-   *           If the managed object was found but its type could not
-   *           be determined.
-   * @throws PropertyException
-   *           If the managed object was found but the requested
-   *           property could not be decoded.
-   * @throws ManagedObjectNotFoundException
-   *           If the requested managed object could not be found on
-   *           the server.
-   * @throws AuthorizationException
-   *           If the server refuses to retrieve the managed object
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public abstract <C extends ConfigurationClient, S extends Configuration, PD>
-  SortedSet<PD> getPropertyValues(
-      ManagedObjectPath<C, S> path, PropertyDefinition<PD> pd)
-      throws IllegalArgumentException, DefinitionDecodingException,
-      AuthorizationException, ManagedObjectNotFoundException,
-      CommunicationException, PropertyException;
-
-
-
-  /**
-   * Gets the root configuration managed object associated with this
-   * management context driver.
-   *
-   * @return Returns the root configuration managed object associated
-   *         with this management context driver.
-   */
-  public abstract
-  ManagedObject<RootCfgClient> getRootConfigurationManagedObject();
-
-
-
-  /**
-   * Lists the child managed objects of the named parent managed
-   * object which are a sub-type of the specified managed object
-   * definition.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param parent
-   *          The path of the parent managed object.
-   * @param rd
-   *          The instantiable relation definition.
-   * @param d
-   *          The managed object definition.
-   * @return Returns the names of the child managed objects which are
-   *         a sub-type of the specified managed object definition.
-   * @throws IllegalArgumentException
-   *           If the relation definition is not associated with the
-   *           parent managed object's definition.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws AuthorizationException
-   *           If the server refuses to list the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public abstract <C extends ConfigurationClient, S extends Configuration>
-  String[] listManagedObjects(
-      ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd,
-      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
-      throws IllegalArgumentException, ManagedObjectNotFoundException,
-      AuthorizationException, CommunicationException;
-
-
-
-  /**
-   * Lists the child managed objects of the named parent managed
-   * object which are a sub-type of the specified managed object
-   * definition.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param parent
-   *          The path of the parent managed object.
-   * @param rd
-   *          The set relation definition.
-   * @param d
-   *          The managed object definition.
-   * @return Returns the names of the child managed objects which are
-   *         a sub-type of the specified managed object definition.
-   * @throws IllegalArgumentException
-   *           If the relation definition is not associated with the
-   *           parent managed object's definition.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws AuthorizationException
-   *           If the server refuses to list the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public abstract <C extends ConfigurationClient, S extends Configuration>
-  String[] listManagedObjects(
-      ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd,
-      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
-      throws IllegalArgumentException, ManagedObjectNotFoundException,
-      AuthorizationException, CommunicationException;
-
-
-
-  /**
-   * Determines whether or not the named managed object exists.
-   * <p>
-   * Implementations should always return <code>true</code> when the
-   * provided path is empty.
-   *
-   * @param path
-   *          The path of the named managed object.
-   * @return Returns <code>true</code> if the named managed object
-   *         exists, <code>false</code> otherwise.
-   * @throws ManagedObjectNotFoundException
-   *           If the parent managed object could not be found.
-   * @throws AuthorizationException
-   *           If the server refuses to make the determination because
-   *           the client does not have the correct privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  public abstract boolean managedObjectExists(ManagedObjectPath<?, ?> path)
-      throws ManagedObjectNotFoundException, AuthorizationException,
-      CommunicationException;
-
-
-
-  /**
-   * Deletes the named managed object.
-   * <p>
-   * Implementations do not need check whether the named managed
-   * object exists, nor do they need to enforce client constraints.
-   *
-   * @param <C>
-   *          The type of client managed object configuration that the
-   *          relation definition refers to.
-   * @param <S>
-   *          The type of server managed object configuration that the
-   *          relation definition refers to.
-   * @param path
-   *          The path of the managed object to be deleted.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be removed due to some
-   *           server-side constraint which cannot be satisfied (for
-   *           example, if it is referenced by another managed
-   *           object).
-   * @throws AuthorizationException
-   *           If the server refuses to remove the managed objects
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
-   */
-  protected abstract <C extends ConfigurationClient, S extends Configuration>
-  void deleteManagedObject(
-      ManagedObjectPath<C, S> path) throws OperationRejectedException,
-      AuthorizationException, CommunicationException;
-
-
-
-  /**
-   * Gets the default values for the specified property.
-   *
-   * @param <PD>
-   *          The type of the property.
-   * @param p
-   *          The managed object path of the current managed object.
-   * @param pd
-   *          The property definition.
-   * @param isCreate
-   *          Indicates whether the managed object has been created
-   *          yet.
-   * @return Returns the default values for the specified property.
-   * @throws DefaultBehaviorException
-   *           If the default values could not be retrieved or decoded
-   *           properly.
-   */
-  protected final <PD> Collection<PD> findDefaultValues(
-      ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd, boolean isCreate)
-      throws DefaultBehaviorException {
-    DefaultValueFinder<PD> v = new DefaultValueFinder<PD>(p, isCreate);
-    return v.find(p, pd);
-  }
-
-
-
-  /**
-   * Gets the management context associated with this driver.
-   *
-   * @return Returns the management context associated with this
-   *         driver.
-   */
-  protected abstract ManagementContext getManagementContext();
-
-
-
-  /**
-   * Validate that a relation definition belongs to the managed object
-   * referenced by the provided path.
-   *
-   * @param path
-   *          The parent managed object path.
-   * @param rd
-   *          The relation definition.
-   * @throws IllegalArgumentException
-   *           If the relation definition does not belong to the
-   *           managed object definition.
-   */
-  protected final void validateRelationDefinition(ManagedObjectPath<?, ?> path,
-      RelationDefinition<?, ?> rd) throws IllegalArgumentException {
-    AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
-    RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
-    if (tmp != rd) {
-      throw new IllegalArgumentException("The relation " + rd.getName()
-          + " is not associated with a " + d.getName());
-    }
-  }
-
-
-
-  // Remove a managed object, first ensuring that the parent exists,
-  // then ensuring that the child exists, before ensuring that any
-  // constraints are satisfied.
-  private <C extends ConfigurationClient, S extends Configuration>
-  boolean doDeleteManagedObject(
-      ManagedObjectPath<C, S> path) throws ManagedObjectNotFoundException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException {
-    // First make sure that the parent exists.
-    if (!managedObjectExists(path.parent())) {
-      throw new ManagedObjectNotFoundException();
-    }
-
-    // Make sure that the targeted managed object exists.
-    if (!managedObjectExists(path)) {
-      return false;
-    }
-
-    // The targeted managed object is guaranteed to exist, so enforce
-    // any constraints.
-    AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
-    List<Message> messages = new LinkedList<Message>();
-    boolean isAcceptable = true;
-
-    for (Constraint constraint : d.getAllConstraints()) {
-      for (ClientConstraintHandler handler : constraint
-          .getClientConstraintHandlers()) {
-        ManagementContext context = getManagementContext();
-        if (!handler.isDeleteAcceptable(context, path, messages)) {
-          isAcceptable = false;
+        /**
+         * {@inheritDoc}
+         */
+        public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d, Void p) {
+            return Collections.emptySet();
         }
-      }
-      if (!isAcceptable) {
-        break;
-      }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d, Void p) {
+            Collection<String> stringValues = d.getDefaultValues();
+            List<T> values = new ArrayList<T>(stringValues.size());
+
+            for (String stringValue : stringValues) {
+                try {
+                    values.add(nextProperty.decodeValue(stringValue));
+                } catch (IllegalPropertyValueStringException e) {
+                    exception = new DefaultBehaviorException(nextProperty, e);
+                    break;
+                }
+            }
+
+            return values;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Collection<T> visitRelativeInherited(RelativeInheritedDefaultBehaviorProvider<T> d, Void p) {
+            try {
+                return getInheritedProperty(d.getManagedObjectPath(nextPath), d.getManagedObjectDefinition(),
+                        d.getPropertyName());
+            } catch (DefaultBehaviorException e) {
+                exception = e;
+                return Collections.emptySet();
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d, Void p) {
+            return Collections.emptySet();
+        }
+
+        // Find the default values for the next path/property.
+        private Collection<T> find(ManagedObjectPath<?, ?> p, PropertyDefinition<T> pd) throws DefaultBehaviorException {
+            this.nextPath = p;
+            this.nextProperty = pd;
+
+            Collection<T> values = nextProperty.getDefaultBehaviorProvider().accept(this, null);
+
+            if (exception != null) {
+                throw exception;
+            }
+
+            if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+                throw new DefaultBehaviorException(pd, new PropertyIsSingleValuedException(pd));
+            }
+
+            return values;
+        }
+
+        // Get an inherited property value.
+        @SuppressWarnings("unchecked")
+        private Collection<T> getInheritedProperty(ManagedObjectPath target, AbstractManagedObjectDefinition<?, ?> d,
+                String propertyName) throws DefaultBehaviorException {
+            // First check that the requested type of managed object
+            // corresponds to the path.
+            AbstractManagedObjectDefinition<?, ?> supr = target.getManagedObjectDefinition();
+            if (!supr.isParentOf(d)) {
+                throw new DefaultBehaviorException(nextProperty, new DefinitionDecodingException(supr,
+                        Reason.WRONG_TYPE_INFORMATION));
+            }
+
+            // Save the current property in case of recursion.
+            PropertyDefinition<T> pd1 = nextProperty;
+
+            try {
+                // Determine the requested property definition.
+                PropertyDefinition<T> pd2;
+                try {
+                    // FIXME: we use the definition taken from the default
+                    // behavior here when we should really use the exact
+                    // definition of the component being created.
+                    PropertyDefinition<?> pdTmp = d.getPropertyDefinition(propertyName);
+                    pd2 = pd1.getClass().cast(pdTmp);
+                } catch (IllegalArgumentException e) {
+                    throw new PropertyNotFoundException(propertyName);
+                } catch (ClassCastException e) {
+                    // FIXME: would be nice to throw a better exception here.
+                    throw new PropertyNotFoundException(propertyName);
+                }
+
+                // If the path relates to the current managed object and the
+                // managed object is in the process of being created it won't
+                // exist, so we should just use the default values of the
+                // referenced property.
+                if (isCreate && firstPath.equals(target)) {
+                    // Recursively retrieve this property's default values.
+                    Collection<T> tmp = find(target, pd2);
+                    Collection<T> values = new ArrayList<T>(tmp.size());
+                    for (T value : tmp) {
+                        pd1.validateValue(value);
+                        values.add(value);
+                    }
+                    return values;
+                } else {
+                    // FIXME: issue 2481 - this is broken if the referenced
+                    // property
+                    // inherits its defaults from the newly created managed
+                    // object.
+                    return getPropertyValues(target, pd2);
+                }
+            } catch (DefaultBehaviorException e) {
+                // Wrap any errors due to recursion.
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (DefinitionDecodingException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (PropertyNotFoundException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (AuthorizationException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (ManagedObjectNotFoundException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (CommunicationException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            } catch (PropertyException e) {
+                throw new DefaultBehaviorException(pd1, e);
+            }
+        }
+    };
+
+    /**
+     * Creates a new abstract management context.
+     */
+    protected Driver() {
+        // No implementation required.
     }
 
-    if (!isAcceptable) {
-      throw new OperationRejectedException(OperationType.DELETE, d
-          .getUserFriendlyName(), messages);
+    /**
+     * Closes any context associated with this management context driver.
+     */
+    public void close() {
+        // do nothing by default
     }
 
-    deleteManagedObject(path);
-    return true;
-  }
+    /**
+     * Deletes the named instantiable child managed object from the named parent
+     * managed object.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param parent
+     *            The path of the parent managed object.
+     * @param rd
+     *            The instantiable relation definition.
+     * @param name
+     *            The name of the child managed object to be removed.
+     * @return Returns <code>true</code> if the named instantiable child managed
+     *         object was found, or <code>false</code> if it was not found.
+     * @throws IllegalArgumentException
+     *             If the relation definition is not associated with the parent
+     *             managed object's definition.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be removed due to some
+     *             client-side or server-side constraint which cannot be
+     *             satisfied (for example, if it is referenced by another
+     *             managed object).
+     * @throws AuthorizationException
+     *             If the server refuses to remove the managed objects because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject(
+            ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd, String name)
+            throws IllegalArgumentException, ManagedObjectNotFoundException, OperationRejectedException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(parent, rd);
+        ManagedObjectPath<?, ?> child = parent.child(rd, name);
+        return doDeleteManagedObject(child);
+    }
+
+    /**
+     * Deletes the optional child managed object from the named parent managed
+     * object.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param parent
+     *            The path of the parent managed object.
+     * @param rd
+     *            The optional relation definition.
+     * @return Returns <code>true</code> if the optional child managed object
+     *         was found, or <code>false</code> if it was not found.
+     * @throws IllegalArgumentException
+     *             If the relation definition is not associated with the parent
+     *             managed object's definition.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be removed due to some
+     *             client-side or server-side constraint which cannot be
+     *             satisfied (for example, if it is referenced by another
+     *             managed object).
+     * @throws AuthorizationException
+     *             If the server refuses to remove the managed objects because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject(
+            ManagedObjectPath<?, ?> parent, OptionalRelationDefinition<C, S> rd) throws IllegalArgumentException,
+            ManagedObjectNotFoundException, OperationRejectedException, AuthorizationException, CommunicationException {
+        validateRelationDefinition(parent, rd);
+        ManagedObjectPath<?, ?> child = parent.child(rd);
+        return doDeleteManagedObject(child);
+    }
+
+    /**
+     * Deletes the named instantiable child managed object from the named parent
+     * managed object.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param parent
+     *            The path of the parent managed object.
+     * @param rd
+     *            The instantiable relation definition.
+     * @param name
+     *            The name of the child managed object to be removed.
+     * @return Returns <code>true</code> if the named instantiable child managed
+     *         object was found, or <code>false</code> if it was not found.
+     * @throws IllegalArgumentException
+     *             If the relation definition is not associated with the parent
+     *             managed object's definition.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be removed due to some
+     *             client-side or server-side constraint which cannot be
+     *             satisfied (for example, if it is referenced by another
+     *             managed object).
+     * @throws AuthorizationException
+     *             If the server refuses to remove the managed objects because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject(
+            ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd, String name)
+            throws IllegalArgumentException, ManagedObjectNotFoundException, OperationRejectedException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(parent, rd);
+        ManagedObjectPath<?, ?> child = parent.child(rd, name);
+        return doDeleteManagedObject(child);
+    }
+
+    /**
+     * Gets the named managed object. The path is guaranteed to be non-empty, so
+     * implementations do not need to worry about handling this special case.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the path
+     *            definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the path
+     *            definition refers to.
+     * @param path
+     *            The non-empty path of the managed object.
+     * @return Returns the named managed object.
+     * @throws DefinitionDecodingException
+     *             If the managed object was found but its type could not be
+     *             determined.
+     * @throws ManagedObjectDecodingException
+     *             If the managed object was found but one or more of its
+     *             properties could not be decoded.
+     * @throws ManagedObjectNotFoundException
+     *             If the requested managed object could not be found on the
+     *             server.
+     * @throws AuthorizationException
+     *             If the server refuses to retrieve the managed object because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public abstract <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getManagedObject(
+            ManagedObjectPath<C, S> path) throws DefinitionDecodingException, ManagedObjectDecodingException,
+            ManagedObjectNotFoundException, AuthorizationException, CommunicationException;
+
+    /**
+     * Gets the effective values of a property in the named managed object.
+     * <p>
+     * Implementations MUST NOT not use
+     * {@link #getManagedObject(ManagedObjectPath)} to read the referenced
+     * managed object in its entirety. Specifically, implementations MUST only
+     * attempt to resolve the default values for the requested property and its
+     * dependencies (if it uses inherited defaults). This is to avoid infinite
+     * recursion where a managed object contains a property which inherits
+     * default values from another property in the same managed object.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the path
+     *            definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the path
+     *            definition refers to.
+     * @param <PD>
+     *            The type of the property to be retrieved.
+     * @param path
+     *            The path of the managed object containing the property.
+     * @param pd
+     *            The property to be retrieved.
+     * @return Returns the property's effective values, or an empty set if there
+     *         are no values defined.
+     * @throws IllegalArgumentException
+     *             If the property definition is not associated with the
+     *             referenced managed object's definition.
+     * @throws DefinitionDecodingException
+     *             If the managed object was found but its type could not be
+     *             determined.
+     * @throws PropertyException
+     *             If the managed object was found but the requested property
+     *             could not be decoded.
+     * @throws ManagedObjectNotFoundException
+     *             If the requested managed object could not be found on the
+     *             server.
+     * @throws AuthorizationException
+     *             If the server refuses to retrieve the managed object because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public abstract <C extends ConfigurationClient, S extends Configuration, PD> SortedSet<PD> getPropertyValues(
+            ManagedObjectPath<C, S> path, PropertyDefinition<PD> pd) throws IllegalArgumentException,
+            DefinitionDecodingException, AuthorizationException, ManagedObjectNotFoundException,
+            CommunicationException, PropertyException;
+
+    /**
+     * Gets the root configuration managed object associated with this
+     * management context driver.
+     *
+     * @return Returns the root configuration managed object associated with
+     *         this management context driver.
+     */
+    public abstract ManagedObject<RootCfgClient> getRootConfigurationManagedObject();
+
+    /**
+     * Lists the child managed objects of the named parent managed object which
+     * are a sub-type of the specified managed object definition.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param parent
+     *            The path of the parent managed object.
+     * @param rd
+     *            The instantiable relation definition.
+     * @param d
+     *            The managed object definition.
+     * @return Returns the names of the child managed objects which are a
+     *         sub-type of the specified managed object definition.
+     * @throws IllegalArgumentException
+     *             If the relation definition is not associated with the parent
+     *             managed object's definition.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws AuthorizationException
+     *             If the server refuses to list the managed objects because the
+     *             client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public abstract <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects(
+            ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd,
+            AbstractManagedObjectDefinition<? extends C, ? extends S> d) throws IllegalArgumentException,
+            ManagedObjectNotFoundException, AuthorizationException, CommunicationException;
+
+    /**
+     * Lists the child managed objects of the named parent managed object which
+     * are a sub-type of the specified managed object definition.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param parent
+     *            The path of the parent managed object.
+     * @param rd
+     *            The set relation definition.
+     * @param d
+     *            The managed object definition.
+     * @return Returns the names of the child managed objects which are a
+     *         sub-type of the specified managed object definition.
+     * @throws IllegalArgumentException
+     *             If the relation definition is not associated with the parent
+     *             managed object's definition.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws AuthorizationException
+     *             If the server refuses to list the managed objects because the
+     *             client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public abstract <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects(
+            ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd,
+            AbstractManagedObjectDefinition<? extends C, ? extends S> d) throws IllegalArgumentException,
+            ManagedObjectNotFoundException, AuthorizationException, CommunicationException;
+
+    /**
+     * Determines whether or not the named managed object exists.
+     * <p>
+     * Implementations should always return <code>true</code> when the provided
+     * path is empty.
+     *
+     * @param path
+     *            The path of the named managed object.
+     * @return Returns <code>true</code> if the named managed object exists,
+     *         <code>false</code> otherwise.
+     * @throws ManagedObjectNotFoundException
+     *             If the parent managed object could not be found.
+     * @throws AuthorizationException
+     *             If the server refuses to make the determination because the
+     *             client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    public abstract boolean managedObjectExists(ManagedObjectPath<?, ?> path) throws ManagedObjectNotFoundException,
+            AuthorizationException, CommunicationException;
+
+    /**
+     * Deletes the named managed object.
+     * <p>
+     * Implementations do not need check whether the named managed object
+     * exists, nor do they need to enforce client constraints.
+     *
+     * @param <C>
+     *            The type of client managed object configuration that the
+     *            relation definition refers to.
+     * @param <S>
+     *            The type of server managed object configuration that the
+     *            relation definition refers to.
+     * @param path
+     *            The path of the managed object to be deleted.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be removed due to some
+     *             server-side constraint which cannot be satisfied (for
+     *             example, if it is referenced by another managed object).
+     * @throws AuthorizationException
+     *             If the server refuses to remove the managed objects because
+     *             the client does not have the correct privileges.
+     * @throws CommunicationException
+     *             If the client cannot contact the server due to an underlying
+     *             communication problem.
+     */
+    protected abstract <C extends ConfigurationClient, S extends Configuration> void deleteManagedObject(
+            ManagedObjectPath<C, S> path) throws OperationRejectedException, AuthorizationException,
+            CommunicationException;
+
+    /**
+     * Gets the default values for the specified property.
+     *
+     * @param <PD>
+     *            The type of the property.
+     * @param p
+     *            The managed object path of the current managed object.
+     * @param pd
+     *            The property definition.
+     * @param isCreate
+     *            Indicates whether the managed object has been created yet.
+     * @return Returns the default values for the specified property.
+     * @throws DefaultBehaviorException
+     *             If the default values could not be retrieved or decoded
+     *             properly.
+     */
+    protected final <PD> Collection<PD> findDefaultValues(ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd,
+            boolean isCreate) throws DefaultBehaviorException {
+        DefaultValueFinder<PD> v = new DefaultValueFinder<PD>(p, isCreate);
+        return v.find(p, pd);
+    }
+
+    /**
+     * Gets the management context associated with this driver.
+     *
+     * @return Returns the management context associated with this driver.
+     */
+    protected abstract ManagementContext getManagementContext();
+
+    /**
+     * Validate that a relation definition belongs to the managed object
+     * referenced by the provided path.
+     *
+     * @param path
+     *            The parent managed object path.
+     * @param rd
+     *            The relation definition.
+     * @throws IllegalArgumentException
+     *             If the relation definition does not belong to the managed
+     *             object definition.
+     */
+    protected final void validateRelationDefinition(ManagedObjectPath<?, ?> path, RelationDefinition<?, ?> rd)
+            throws IllegalArgumentException {
+        AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
+        RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
+        if (tmp != rd) {
+            throw new IllegalArgumentException("The relation " + rd.getName() + " is not associated with a "
+                    + d.getName());
+        }
+    }
+
+    // Remove a managed object, first ensuring that the parent exists,
+    // then ensuring that the child exists, before ensuring that any
+    // constraints are satisfied.
+    private <C extends ConfigurationClient, S extends Configuration> boolean doDeleteManagedObject(
+            ManagedObjectPath<C, S> path) throws ManagedObjectNotFoundException, OperationRejectedException,
+            AuthorizationException, CommunicationException {
+        // First make sure that the parent exists.
+        if (!managedObjectExists(path.parent())) {
+            throw new ManagedObjectNotFoundException();
+        }
+
+        // Make sure that the targeted managed object exists.
+        if (!managedObjectExists(path)) {
+            return false;
+        }
+
+        // The targeted managed object is guaranteed to exist, so enforce
+        // any constraints.
+        AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
+        List<LocalizableMessage> messages = new LinkedList<LocalizableMessage>();
+        boolean isAcceptable = true;
+
+        for (Constraint constraint : d.getAllConstraints()) {
+            for (ClientConstraintHandler handler : constraint.getClientConstraintHandlers()) {
+                ManagementContext context = getManagementContext();
+                if (!handler.isDeleteAcceptable(context, path, messages)) {
+                    isAcceptable = false;
+                }
+            }
+            if (!isAcceptable) {
+                break;
+            }
+        }
+
+        if (!isAcceptable) {
+            throw new OperationRejectedException(OperationType.DELETE, d.getUserFriendlyName(), messages);
+        }
+
+        deleteManagedObject(path);
+        return true;
+    }
 
 }

--
Gitblit v1.10.0