From b8b853dc80f789c90f3159a35f75966034a289aa Mon Sep 17 00:00:00 2001
From: sin <sin@localhost>
Date: Fri, 10 Jul 2009 18:58:37 +0000
Subject: [PATCH] issue 4102: Provide implementation for substitution syntax

---
 opends/src/server/org/opends/server/backends/SchemaBackend.java |  203 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 203 insertions(+), 0 deletions(-)

diff --git a/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 056da63..a69218f 100644
--- a/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -78,6 +78,7 @@
 import org.opends.server.schema.DITContentRuleSyntax;
 import org.opends.server.schema.DITStructureRuleSyntax;
 import org.opends.server.schema.GeneralizedTimeSyntax;
+import org.opends.server.schema.LDAPSyntaxDescriptionSyntax;
 import org.opends.server.schema.MatchingRuleUseSyntax;
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
@@ -1270,6 +1271,34 @@
               addMatchingRuleUse(mru, newSchema, modifiedSchemaFiles);
             }
           }
+          else if(at.equals(ldapSyntaxesType))
+          {
+            for(AttributeValue v : a)
+            {
+              LDAPSyntaxDescription lsd = null;
+              try
+              {
+                lsd = LDAPSyntaxDescriptionSyntax.decodeLDAPSyntax(
+                        v.getValue(),
+                        newSchema, false);
+              }
+              catch(DirectoryException de)
+              {
+                if (debugEnabled())
+                {
+                  TRACER.debugCaught(DebugLogLevel.ERROR, de);
+                }
+
+                Message message =
+                        ERR_SCHEMA_MODIFY_CANNOT_DECODE_LDAP_SYNTAX.get(
+                            v.getValue().toString(), de.getMessageObject());
+                throw new DirectoryException(
+                               ResultCode.INVALID_ATTRIBUTE_SYNTAX, message,
+                               de);
+              }
+              addLdapSyntaxDescription(lsd,newSchema,modifiedSchemaFiles);
+            }
+          }
           else
           {
             Message message =
@@ -1456,6 +1485,34 @@
                                     modifiedSchemaFiles);
             }
           }
+          else if (at.equals(ldapSyntaxesType))
+          {
+            for(AttributeValue v : a)
+            {
+              LDAPSyntaxDescription lsd = null;
+              try
+              {
+                lsd = LDAPSyntaxDescriptionSyntax.decodeLDAPSyntax(
+                        v.getValue(),
+                        newSchema, false);
+              }
+              catch(DirectoryException de)
+              {
+                if (debugEnabled())
+                {
+                  TRACER.debugCaught(DebugLogLevel.ERROR, de);
+                }
+
+                Message message =
+                        ERR_SCHEMA_MODIFY_CANNOT_DECODE_LDAP_SYNTAX.get(
+                          v.getValue().toString(), de.getMessageObject());
+                throw new DirectoryException(
+                               ResultCode.INVALID_ATTRIBUTE_SYNTAX, message,
+                               de);
+              }
+              removeLdapSyntaxDescription(lsd,newSchema,modifiedSchemaFiles);
+            }
+          }
           else
           {
             Message message =
@@ -3229,6 +3286,125 @@
 
 
   /**
+   * Handles all processing required for adding the provided ldap syntax
+   * description to the given schema, replacing an existing ldap syntax
+   * description if necessary, and ensuring all other metadata is properly
+   * updated.
+   *
+   * @param  ldapSyntaxDesc   The ldap syntax description to add or replace in
+   *                               the server schema.
+   * @param  schema               The schema to which the name form should be
+   *                              added.
+   * @param  modifiedSchemaFiles  The names of the schema files containing
+   *                              schema elements that have been updated as part
+   *                              of the schema modification.
+   *
+   * @throws  DirectoryException  If a problem occurs while attempting to add
+   *                              the provided ldap syntax description to the
+   *                              server schema.
+   */
+  private void addLdapSyntaxDescription(LDAPSyntaxDescription ldapSyntaxDesc,
+                           Schema schema,
+                           Set<String> modifiedSchemaFiles)
+          throws DirectoryException
+  {
+       //Check if there is an existing syntax with this oid.
+    String oid = ldapSyntaxDesc.getLdapSyntaxDescriptionSyntax().getOID();
+
+    // We allow only unimplemented syntaxes to be substituted.
+    if(schema.getSyntax(oid) !=null)
+    {
+      Message message = ERR_ATTR_SYNTAX_INVALID_SUBSTITUTION_SYNTAX.get(
+              ldapSyntaxDesc.getDefinition(),oid);
+      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
+                                     message);
+    }
+
+    LDAPSyntaxDescription existingLSD =
+         schema.getLdapSyntaxDescription(oid);
+
+    // If there is no existing lsd, then we're adding a new ldapsyntax.
+    // Otherwise, we're replacing an existing one.
+    if (existingLSD == null)
+    {
+      schema.registerLdapSyntaxDescription(ldapSyntaxDesc, false);
+      String schemaFile = ldapSyntaxDesc.getSchemaFile();
+      if ((schemaFile == null) || (schemaFile.length() == 0))
+      {
+        schemaFile = FILE_USER_SCHEMA_ELEMENTS;
+        ldapSyntaxDesc.setSchemaFile(schemaFile);
+      }
+
+      modifiedSchemaFiles.add(schemaFile);
+    }
+    else
+    {
+      schema.deregisterLdapSyntaxDescription(existingLSD);
+      schema.registerLdapSyntaxDescription(ldapSyntaxDesc, false);
+      schema.rebuildDependentElements(existingLSD);
+
+      if ((ldapSyntaxDesc.getSchemaFile() == null) ||
+          (ldapSyntaxDesc.getSchemaFile().length() == 0))
+      {
+        String schemaFile = ldapSyntaxDesc.getSchemaFile();
+        if ((schemaFile == null) || (schemaFile.length() == 0))
+        {
+          schemaFile = FILE_USER_SCHEMA_ELEMENTS;
+        }
+
+        ldapSyntaxDesc.setSchemaFile(schemaFile);
+        modifiedSchemaFiles.add(schemaFile);
+      }
+      else
+      {
+        String newSchemaFile = ldapSyntaxDesc.getSchemaFile();
+        String oldSchemaFile = existingLSD.getSchemaFile();
+        if ((oldSchemaFile == null) || oldSchemaFile.equals(newSchemaFile))
+        {
+          modifiedSchemaFiles.add(newSchemaFile);
+        }
+        else
+        {
+          modifiedSchemaFiles.add(newSchemaFile);
+          modifiedSchemaFiles.add(oldSchemaFile);
+        }
+      }
+    }
+  }
+
+
+
+  //Gets rid of the ldap syntax description.
+  private void removeLdapSyntaxDescription(LDAPSyntaxDescription ldapSyntaxDesc,
+                                    Schema schema,
+                                    Set<String> modifiedSchemaFiles)
+          throws DirectoryException
+  {
+    //See if the specified ldap syntax description is actually defined in the
+    //server schema.  If not, then fail. Note that we are checking only the
+     //real part of the ldapsyntaxes attribute. A virtual value is not searched
+      // and hence never deleted.
+    String oid = ldapSyntaxDesc.getLdapSyntaxDescriptionSyntax().getOID();
+    LDAPSyntaxDescription removeLSD = schema.getLdapSyntaxDescription(oid);
+
+    if ((removeLSD == null) || (! removeLSD.equals(ldapSyntaxDesc)))
+    {
+      Message message =
+          ERR_SCHEMA_MODIFY_REMOVE_NO_SUCH_LSD.get(oid);
+      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+    }
+
+    schema.deregisterLdapSyntaxDescription(removeLSD);
+    String schemaFile = removeLSD.getSchemaFile();
+    if (schemaFile != null)
+    {
+      modifiedSchemaFiles.add(schemaFile);
+    }
+  }
+
+
+
+  /**
    * Creates an empty entry that may be used as the basis for a new schema file.
    *
    * @return  An empty entry that may be used as the basis for a new schema
@@ -3439,6 +3615,33 @@
       schemaEntry.putAttribute(matchingRuleUsesType, attrList);
     }
 
+
+    /**
+     * Add all of the ldap syntax descriptions to the schema entry. We do
+     * this only for the real part of the ldapsyntaxes attribute. The real part
+     * is read and write to/from the schema files.
+     */
+    values = new LinkedHashSet<AttributeValue>();
+    for (LDAPSyntaxDescription ldapSyntax :
+                                   schema.getLdapSyntaxDescriptions().values())
+    {
+      if(schemaFile.equals(ldapSyntax.getSchemaFile()))
+      {
+        values.add(AttributeValues.create(ldapSyntaxesType,
+                ldapSyntax.getDefinition()));
+      }
+    }
+
+   if (! values.isEmpty())
+   {
+     ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+     AttributeBuilder builder = new AttributeBuilder(ldapSyntaxesType);
+     builder.addAll(values);
+     attrList.add(builder.toAttribute());
+     schemaEntry.putAttribute(attributeTypesType, attrList);
+   }
+
+
     if (schemaFile.equals(FILE_USER_SCHEMA_ELEMENTS))
     {
       Map<String, Attribute> attributes = schema.getExtraAttributes();

--
Gitblit v1.10.0