From 70b0e3d553e5a2a896337730b6c0540488b78f08 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 10 Dec 2013 12:43:16 +0000
Subject: [PATCH] OpenDJ 3 : config framework

---
 opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java |  561 +++++++++++++++++++++++++------------------------------
 1 files changed, 254 insertions(+), 307 deletions(-)

diff --git a/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index be57134..243b260 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -27,20 +27,21 @@
 
 package org.opends.server.admin.client.ldap;
 
-
-
-import javax.naming.NameAlreadyBoundException;
-import javax.naming.NamingException;
-import javax.naming.NoPermissionException;
-import javax.naming.OperationNotSupportedException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
+import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.LinkedAttribute;
+import org.forgerock.opendj.ldap.LinkedHashMapEntry;
+import org.forgerock.opendj.ldap.ModificationType;
+import org.forgerock.opendj.ldap.RDN;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+import org.forgerock.opendj.ldap.requests.Requests;
 import org.opends.server.admin.AggregationPropertyDefinition;
 import org.opends.server.admin.Configuration;
 import org.opends.server.admin.ConfigurationClient;
@@ -56,8 +57,6 @@
 import org.opends.server.admin.RelationDefinition;
 import org.opends.server.admin.SetRelationDefinition;
 import org.opends.server.admin.UnknownPropertyDefinitionException;
-import org.opends.server.admin.client.AuthorizationException;
-import org.opends.server.admin.client.CommunicationException;
 import org.opends.server.admin.client.ConcurrentModificationException;
 import org.opends.server.admin.client.ManagedObject;
 import org.opends.server.admin.client.OperationRejectedException;
@@ -67,320 +66,268 @@
 import org.opends.server.admin.client.spi.Property;
 import org.opends.server.admin.client.spi.PropertySet;
 
-
-
 /**
  * A managed object bound to an LDAP connection.
  *
  * @param <T>
- *          The type of client configuration represented by the client
- *          managed object.
+ *            The type of client configuration represented by the client managed
+ *            object.
  */
-final class LDAPManagedObject<T extends ConfigurationClient> extends
-    AbstractManagedObject<T> {
+final class LDAPManagedObject<T extends ConfigurationClient> extends AbstractManagedObject<T> {
 
-  /**
-   * A visitor which is used to encode property LDAP values.
-   */
-  private static final class ValueEncoder extends
-      PropertyValueVisitor<Object, Void> {
+    /**
+     * A visitor which is used to encode property LDAP values.
+     */
+    private static final class ValueEncoder extends PropertyValueVisitor<Object, Void> {
 
-    // Prevent instantiation.
-    private ValueEncoder() {
-      // No implementation required.
+        // Prevent instantiation.
+        private ValueEncoder() {
+            // No implementation required.
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public <C extends ConfigurationClient, S extends Configuration> Object visitAggregation(
+                AggregationPropertyDefinition<C, S> pd, String v, Void p) {
+            // Aggregations values are stored as full DNs in LDAP, but
+            // just their common name is exposed in the admin framework.
+            Reference<C, S> reference = Reference.parseName(pd.getParentPath(), pd.getRelationDefinition(), v);
+            return reference.toDN().toString();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public <PD> Object visitUnknown(PropertyDefinition<PD> pd, PD v, Void p)
+                throws UnknownPropertyDefinitionException {
+            return pd.encodeValue(v);
+        }
     }
 
+    // The LDAP management driver associated with this managed object.
+    private final LDAPDriver driver;
 
+    /**
+     * Creates a new LDAP managed object instance.
+     *
+     * @param driver
+     *            The underlying LDAP management driver.
+     * @param d
+     *            The managed object's definition.
+     * @param path
+     *            The managed object's path.
+     * @param properties
+     *            The managed object's properties.
+     * @param existsOnServer
+     *            Indicates whether or not the managed object already exists.
+     * @param namingPropertyDefinition
+     *            The managed object's naming property definition if there is
+     *            one.
+     */
+    LDAPManagedObject(LDAPDriver driver, ManagedObjectDefinition<T, ? extends Configuration> d,
+            ManagedObjectPath<T, ? extends Configuration> path, PropertySet properties, boolean existsOnServer,
+            PropertyDefinition<?> namingPropertyDefinition) {
+        super(d, path, properties, existsOnServer, namingPropertyDefinition);
+        this.driver = driver;
+    }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public <C extends ConfigurationClient, S extends Configuration>
-    Object visitAggregation(
-        AggregationPropertyDefinition<C, S> pd, String v, Void p) {
-      // Aggregations values are stored as full DNs in LDAP, but
-      // just their common name is exposed in the admin framework.
-      Reference<C, S> reference = Reference.parseName(pd.getParentPath(), pd
-          .getRelationDefinition(), v);
-      return reference.toDN().toString();
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public <PD> Object visitUnknown(PropertyDefinition<PD> pd, PD v, Void p)
-        throws UnknownPropertyDefinitionException {
-      return pd.encodeValue(v);
-    }
-  }
-
-
-
-  // The LDAP management driver associated with this managed object.
-  private final LDAPDriver driver;
-
-
-
-  /**
-   * Creates a new LDAP managed object instance.
-   *
-   * @param driver
-   *          The underlying LDAP management driver.
-   * @param d
-   *          The managed object's definition.
-   * @param path
-   *          The managed object's path.
-   * @param properties
-   *          The managed object's properties.
-   * @param existsOnServer
-   *          Indicates whether or not the managed object already
-   *          exists.
-   * @param namingPropertyDefinition
-   *          The managed object's naming property definition if there
-   *          is one.
-   */
-  LDAPManagedObject(LDAPDriver driver,
-      ManagedObjectDefinition<T, ? extends Configuration> d,
-      ManagedObjectPath<T, ? extends Configuration> path,
-      PropertySet properties, boolean existsOnServer,
-      PropertyDefinition<?> namingPropertyDefinition) {
-    super(d, path, properties, existsOnServer, namingPropertyDefinition);
-    this.driver = driver;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected void addNewManagedObject() throws AuthorizationException,
-      CommunicationException, OperationRejectedException,
-      ConcurrentModificationException, ManagedObjectAlreadyExistsException {
-    // First make sure that the parent managed object still exists.
-    ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
-    ManagedObjectPath<?, ?> path = getManagedObjectPath();
-    ManagedObjectPath<?, ?> parent = path.parent();
-
-    try {
-      if (!driver.managedObjectExists(parent)) {
-        throw new ConcurrentModificationException();
-      }
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-
-    // We may need to create the parent "relation" entry if this is a
-    // child of an instantiable or set relation.
-    RelationDefinition<?, ?> r = path.getRelationDefinition();
-    if (r instanceof InstantiableRelationDefinition
-        || r instanceof SetRelationDefinition) {
-
-      // TODO: this implementation does not handle relations which
-      // comprise of more than one RDN arc (this will probably never
-      // be required anyway).
-      LdapName dn;
-      if (r instanceof InstantiableRelationDefinition) {
-        dn = LDAPNameBuilder.create(parent,
-            (InstantiableRelationDefinition) r, driver.getLDAPProfile());
-      } else {
-        dn = LDAPNameBuilder.create(parent,
-            (SetRelationDefinition) r, driver.getLDAPProfile());
-      }
-
-      if (!driver.entryExists(dn)) {
-        // We need to create the entry.
-        Attributes attributes = new BasicAttributes();
-
-        // Create the branch's object class attribute.
-        Attribute oc = new BasicAttribute("objectClass");
-        for (String objectClass : driver.getLDAPProfile()
-            .getRelationObjectClasses(r)) {
-          oc.add(objectClass);
-        }
-        attributes.put(oc);
-
-        // Create the branch's naming attribute.
-        Rdn rdn = dn.getRdn(dn.size() - 1);
-        attributes.put(rdn.getType(), rdn.getValue().toString());
-
-        // Create the entry.
-        try {
-          driver.getLDAPConnection().createEntry(dn, attributes);
-        } catch (OperationNotSupportedException e) {
-          // Unwilling to perform.
-          if (e.getMessage() == null) {
-            throw new OperationRejectedException(OperationType.CREATE, d
-                .getUserFriendlyName());
-          } else {
-            LocalizableMessage m = LocalizableMessage.raw("%s", e.getMessage());
-            throw new OperationRejectedException(OperationType.CREATE, d
-                .getUserFriendlyName(), m);
-          }
-        } catch (NamingException e) {
-          driver.adaptNamingException(e);
-        }
-      }
-    }
-
-    // Now add the entry representing this new managed object.
-    LdapName dn = LDAPNameBuilder.create(path, driver.getLDAPProfile());
-    Attributes attributes = new BasicAttributes(true);
-
-    // Create the object class attribute.
-    Attribute oc = new BasicAttribute("objectclass");
-    ManagedObjectDefinition<?, ?> definition = getManagedObjectDefinition();
-    for (String objectClass : driver.getLDAPProfile().getObjectClasses(
-        definition)) {
-      oc.add(objectClass);
-    }
-    attributes.put(oc);
-
-    // Create the naming attribute if there is not naming property.
-    PropertyDefinition<?> npd = getNamingPropertyDefinition();
-    if (npd == null) {
-      Rdn rdn = dn.getRdn(dn.size() - 1);
-      attributes.put(rdn.getType(), rdn.getValue().toString());
-    }
-
-    // Create the remaining attributes.
-    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
-      String attrID = driver.getLDAPProfile().getAttributeName(definition, pd);
-      Attribute attribute = new BasicAttribute(attrID);
-      encodeProperty(attribute, pd);
-      if (attribute.size() != 0) {
-        attributes.put(attribute);
-      }
-    }
-
-    try {
-      // Create the entry.
-      driver.getLDAPConnection().createEntry(dn, attributes);
-    } catch (NameAlreadyBoundException e) {
-      throw new ManagedObjectAlreadyExistsException();
-    } catch (OperationNotSupportedException e) {
-      // Unwilling to perform.
-      if (e.getMessage() == null) {
-        throw new OperationRejectedException(OperationType.CREATE, d
-            .getUserFriendlyName());
-      } else {
-        LocalizableMessage m = LocalizableMessage.raw("%s", e.getMessage());
-        throw new OperationRejectedException(OperationType.CREATE, d
-            .getUserFriendlyName(), m);
-      }
-    } catch (NamingException e) {
-      driver.adaptNamingException(e);
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected Driver getDriver() {
-    return driver;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected void modifyExistingManagedObject()
-      throws ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException {
-    // Build the list of modified attributes.
-    Attributes mods = new BasicAttributes();
-    ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-      Property<?> p = getProperty(pd);
-      if (p.isModified()) {
-        String attrID = driver.getLDAPProfile().getAttributeName(d, pd);
-        Attribute attribute = new BasicAttribute(attrID);
-        encodeProperty(attribute, pd);
-        mods.put(attribute);
-      }
-    }
-
-    // Perform the LDAP modification if something has changed.
-    if (mods.size() > 0) {
-      try {
+    protected void addNewManagedObject() throws ErrorResultException, OperationRejectedException,
+            ConcurrentModificationException, ManagedObjectAlreadyExistsException {
+        // First make sure that the parent managed object still exists.
+        ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
         ManagedObjectPath<?, ?> path = getManagedObjectPath();
-        LdapName dn = LDAPNameBuilder.create(path, driver.getLDAPProfile());
-        driver.getLDAPConnection().modifyEntry(dn, mods);
-      } catch (NoPermissionException e) {
-        throw new AuthorizationException(e);
-      } catch (OperationNotSupportedException e) {
-        // Unwilling to perform.
-        if (e.getMessage() == null) {
-          throw new OperationRejectedException(OperationType.MODIFY, d
-              .getUserFriendlyName());
-        } else {
-          LocalizableMessage m = LocalizableMessage.raw("%s", e.getMessage());
-          throw new OperationRejectedException(OperationType.MODIFY, d
-              .getUserFriendlyName(), m);
+        ManagedObjectPath<?, ?> parent = path.parent();
+
+        try {
+            if (!driver.managedObjectExists(parent)) {
+                throw new ConcurrentModificationException();
+            }
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
         }
-      } catch (NamingException e) {
-        // Just treat it as a communication problem.
-        throw new CommunicationException(e);
-      }
+
+        // We may need to create the parent "relation" entry if this is a
+        // child of an instantiable or set relation.
+        RelationDefinition<?, ?> r = path.getRelationDefinition();
+        if (r instanceof InstantiableRelationDefinition || r instanceof SetRelationDefinition) {
+
+            // TODO: this implementation does not handle relations which
+            // comprise of more than one RDN arc (this will probably never
+            // be required anyway).
+            DN dn;
+            if (r instanceof InstantiableRelationDefinition) {
+                dn = LDAPNameBuilder.create(parent, (InstantiableRelationDefinition) r, driver.getLDAPProfile());
+            } else {
+                dn = LDAPNameBuilder.create(parent, (SetRelationDefinition) r, driver.getLDAPProfile());
+            }
+
+            if (!driver.entryExists(dn)) {
+                Entry entry = new LinkedHashMapEntry(dn);
+
+                // Create the branch's object class attribute.
+                List<String> objectClasses = driver.getLDAPProfile().getRelationObjectClasses(r);
+                addObjectClassesToEntry(objectClasses, entry);
+
+                // Create the branch's naming attribute.
+                RDN rdn = dn.parent(dn.size() - 1).rdn();
+                entry.addAttribute(rdn.getFirstAVA().toAttribute());
+
+                // Create the entry.
+                try {
+                    driver.getLDAPConnection().createEntry(entry);
+                } catch (ErrorResultException e) {
+                    if (e.getResult().getResultCode() == ResultCode.UNWILLING_TO_PERFORM) {
+                        LocalizableMessage m = LocalizableMessage.raw("%s", e.getLocalizedMessage());
+                        throw new OperationRejectedException(OperationType.CREATE, d.getUserFriendlyName(), m);
+                    } else {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        // Now add the entry representing this new managed object.
+        DN dn = LDAPNameBuilder.create(path, driver.getLDAPProfile());
+        Entry entry = new LinkedHashMapEntry(dn);
+
+        // Create the object class attribute.
+        ManagedObjectDefinition<?, ?> definition = getManagedObjectDefinition();
+        List<String> objectClasses = driver.getLDAPProfile().getObjectClasses(definition);
+        addObjectClassesToEntry(objectClasses, entry);
+
+        // Create the naming attribute if there is not naming property.
+        PropertyDefinition<?> namingPropertyDef = getNamingPropertyDefinition();
+        if (namingPropertyDef == null) {
+            RDN rdn = dn.parent(dn.size() - 1).rdn();
+            entry.addAttribute(rdn.getFirstAVA().toAttribute());
+        }
+
+        // Create the remaining attributes.
+        for (PropertyDefinition<?> propertyDef : definition.getAllPropertyDefinitions()) {
+            String attrID = driver.getLDAPProfile().getAttributeName(definition, propertyDef);
+            Attribute attribute = new LinkedAttribute(attrID);
+            encodeProperty(attribute, propertyDef);
+            if (attribute.size() != 0) {
+                entry.addAttribute(attribute);
+            }
+        }
+
+        try {
+            // Create the entry.
+            driver.getLDAPConnection().createEntry(entry);
+        } catch (ErrorResultException e) {
+            if (e.getResult().getResultCode() == ResultCode.ENTRY_ALREADY_EXISTS) {
+                throw new ManagedObjectAlreadyExistsException();
+            } else if (e.getResult().getResultCode() == ResultCode.UNWILLING_TO_PERFORM) {
+                LocalizableMessage m = LocalizableMessage.raw("%s", e.getLocalizedMessage());
+                throw new OperationRejectedException(OperationType.CREATE, d.getUserFriendlyName(), m);
+            } else {
+                throw e;
+            }
+        }
     }
-  }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected <M extends ConfigurationClient> ManagedObject<M> newInstance(
-      ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> path,
-      PropertySet properties, boolean existsOnServer,
-      PropertyDefinition<?> namingPropertyDefinition) {
-    return new LDAPManagedObject<M>(driver, d, path, properties,
-        existsOnServer, namingPropertyDefinition);
-  }
-
-
-
-  // Encode a property into LDAP string values.
-  private <PD> void encodeProperty(Attribute attribute,
-      PropertyDefinition<PD> pd) {
-    PropertyValueVisitor<Object, Void> visitor = new ValueEncoder();
-    Property<PD> p = getProperty(pd);
-    if (pd.hasOption(PropertyOption.MANDATORY)) {
-      // For mandatory properties we fall-back to the default values
-      // if defined which can sometimes be the case e.g when a
-      // mandatory property is overridden.
-      for (PD value : p.getEffectiveValues()) {
-        attribute.add(pd.accept(visitor, value, null));
-      }
-    } else {
-      for (PD value : p.getPendingValues()) {
-        attribute.add(pd.accept(visitor, value, null));
-      }
+    private void addObjectClassesToEntry(List<String> objectClasses, Entry entry) {
+        for (String objectClass : objectClasses) {
+            Attribute attr = new LinkedAttribute("objectClass");
+            attr.add(ByteString.valueOf(objectClass));
+            entry.addAttribute(attr);
+        }
     }
-  }
 
-  /**
-   * {@inheritDoc}
-   */
-  public boolean isModified() {
-    ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-      Property<?> p = getProperty(pd);
-      if (p.isModified()) {
-        return true;
-      }
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Driver getDriver() {
+        return driver;
     }
-    return false;
-  }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void modifyExistingManagedObject() throws ConcurrentModificationException, OperationRejectedException,
+            ErrorResultException {
+        // Build the modify request
+        ManagedObjectPath<?, ?> path = getManagedObjectPath();
+        DN dn = LDAPNameBuilder.create(path, driver.getLDAPProfile());
+        ModifyRequest request = Requests.newModifyRequest(dn);
+        ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
+        for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+            Property<?> p = getProperty(pd);
+            if (p.isModified()) {
+                String attrID = driver.getLDAPProfile().getAttributeName(d, pd);
+                Attribute attribute = new LinkedAttribute(attrID);
+                encodeProperty(attribute, pd);
+                request.addModification(ModificationType.REPLACE, attrID,
+                        attribute.toArray(new Object[attribute.size()]));
+            }
+        }
+
+        // Perform the LDAP modification if something has changed.
+        if (!request.getModifications().isEmpty()) {
+            try {
+                driver.getLDAPConnection().modifyEntry(request);
+            } catch (ErrorResultException e) {
+                if (e.getResult().getResultCode() == ResultCode.UNWILLING_TO_PERFORM) {
+                    LocalizableMessage m = LocalizableMessage.raw("%s", e.getLocalizedMessage());
+                    throw new OperationRejectedException(OperationType.CREATE, d.getUserFriendlyName(), m);
+                } else {
+                    throw e;
+                }
+            }
+
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected <M extends ConfigurationClient> ManagedObject<M> newInstance(ManagedObjectDefinition<M, ?> d,
+            ManagedObjectPath<M, ?> path, PropertySet properties, boolean existsOnServer,
+            PropertyDefinition<?> namingPropertyDefinition) {
+        return new LDAPManagedObject<M>(driver, d, path, properties, existsOnServer, namingPropertyDefinition);
+    }
+
+    // Encode a property into LDAP string values.
+    private <PD> void encodeProperty(Attribute attribute, PropertyDefinition<PD> propertyDef) {
+        PropertyValueVisitor<Object, Void> visitor = new ValueEncoder();
+        Property<PD> property = getProperty(propertyDef);
+        if (propertyDef.hasOption(PropertyOption.MANDATORY)) {
+            // For mandatory properties we fall-back to the default values
+            // if defined which can sometimes be the case e.g when a
+            // mandatory property is overridden.
+            for (PD value : property.getEffectiveValues()) {
+                attribute.add(propertyDef.accept(visitor, value, null));
+            }
+        } else {
+            for (PD value : property.getPendingValues()) {
+                attribute.add(propertyDef.accept(visitor, value, null));
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isModified() {
+        ManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
+        for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+            Property<?> p = getProperty(pd);
+            if (p.isModified()) {
+                return true;
+            }
+        }
+        return false;
+    }
 
 }

--
Gitblit v1.10.0