From 0aa4dc91310ba40961f5f09009588881d708f17c Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 03 Jun 2016 14:32:11 +0000
Subject: [PATCH] OPENDJ-3037 Use SchemaBuilder.addSchema(Entry, boolean) in SchemaConfigManager

---
 opendj-server-legacy/src/messages/org/opends/messages/config.properties                   |    5 
 opendj-server-legacy/src/test/java/org/opends/server/tasks/AddSchemaFileTaskTestCase.java |   65 ++-
 opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java         |   11 
 opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java                    |  241 ++-------------
 opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java        |  519 ++++++++--------------------------
 5 files changed, 195 insertions(+), 646 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
index 683f9c0..00afecd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
@@ -20,18 +20,19 @@
 import java.io.FilenameFilter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedList;
+import java.util.Collections;
 import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.adapter.server3x.Converters;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.CoreSchema;
-import org.forgerock.opendj.ldap.schema.Syntax;
+import org.forgerock.opendj.ldap.schema.SchemaBuilder;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
@@ -39,12 +40,11 @@
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.Modification;
 import org.opends.server.types.Schema;
+import org.opends.server.types.Schema.SchemaUpdater;
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.StaticUtils;
 
 import static org.opends.messages.ConfigMessages.*;
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.schema.SchemaConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
 /**
@@ -295,21 +295,50 @@
    *                     to be loaded.
    * @param  schemaFile  The name of the schema file to be loaded into the
    *                     provided schema.
-   *
-   * @return  A list of the modifications that could be performed in order to
-   *          obtain the contents of the file.
-   *
    * @throws  ConfigException  If a configuration problem causes the schema
    *                           element initialization to fail.
-   *
    * @throws  InitializationException  If a problem occurs while initializing
    *                                   the schema elements that is not related
    *                                   to the server configuration.
    */
-  public static List<Modification> loadSchemaFile(Schema schema, String schemaFile)
+  public static void loadSchemaFile(Schema schema, String schemaFile)
          throws ConfigException, InitializationException
   {
-    return loadSchemaFile(schema, schemaFile, true);
+    loadSchemaFile(schema, schemaFile, true);
+  }
+
+  /**
+   * Loads the contents of the specified schema file into the provided schema and returns the list
+   * of modifications.
+   *
+   * @param schema
+   *          The schema in which the contents of the schema file are to be loaded.
+   * @param schemaFile
+   *          The name of the schema file to be loaded into the provided schema.
+   * @return A list of the modifications that could be performed in order to obtain the contents of
+   *         the file.
+   * @throws ConfigException
+   *           If a configuration problem causes the schema element initialization to fail.
+   * @throws InitializationException
+   *           If a problem occurs while initializing the schema elements that is not related to the
+   *           server configuration.
+   */
+  public static List<Modification> loadSchemaFileReturnModifications(Schema schema, String schemaFile)
+      throws ConfigException, InitializationException
+  {
+    final Entry entry = loadSchemaFile(schema, schemaFile, true);
+    if (entry != null)
+    {
+      return createAddModifications(entry,
+          CoreSchema.getLDAPSyntaxesAttributeType(),
+          CoreSchema.getAttributeTypesAttributeType(),
+          CoreSchema.getObjectClassesAttributeType(),
+          CoreSchema.getNameFormsAttributeType(),
+          CoreSchema.getDITContentRulesAttributeType(),
+          CoreSchema.getDITStructureRulesAttributeType(),
+          CoreSchema.getMatchingRuleUseAttributeType());
+    }
+    return Collections.emptyList();
   }
 
   /**
@@ -325,20 +354,63 @@
    *                      log an error message and return without an exception.
    *                      This should only be {@code false} when called from
    *                      {@code initializeSchemaFromFiles}.
-   *
-   * @return  A list of the modifications that could be performed in order to
-   *          obtain the contents of the file, or {@code null} if a problem
-   *          occurred and {@code failOnError} is {@code false}.
-   *
+   * @return the schema entry that has been read from the schema file
    * @throws  ConfigException  If a configuration problem causes the schema
    *                           element initialization to fail.
-   *
    * @throws  InitializationException  If a problem occurs while initializing
    *                                   the schema elements that is not related
    *                                   to the server configuration.
    */
-  private static List<Modification> loadSchemaFile(Schema schema, String schemaFile,
-      boolean failOnError) throws ConfigException, InitializationException
+  private static Entry loadSchemaFile(Schema schema, String schemaFile, boolean failOnError)
+      throws ConfigException, InitializationException
+  {
+    final Entry entry = readSchemaEntryFromFile(schemaFile, failOnError);
+    if (entry != null)
+    {
+      List<Attribute> ldapSyntaxList = entry.getAttribute(CoreSchema.getLDAPSyntaxesAttributeType());
+      parseLdapSyntaxesDefinitions(schema, schemaFile, failOnError, ldapSyntaxList);
+
+      updateSchemaWithEntry(schema, schemaFile, failOnError, entry);
+    }
+    return entry;
+  }
+
+  private static void updateSchemaWithEntry(Schema schema, String schemaFile, boolean failOnError, final Entry entry)
+      throws ConfigException
+  {
+    final org.forgerock.opendj.ldap.Entry schemaEntry = Converters.from(entry);
+    try
+    {
+      updateSchema(schema, schemaEntry, false);
+    }
+    catch (DirectoryException e)
+    {
+      if (e.getResultCode().equals(ResultCode.CONSTRAINT_VIOLATION))
+      {
+        // Register it with the schema. We will allow duplicates, with the
+        // later definition overriding any earlier definition, but we want
+        // to trap them and log a warning.
+        logger.warn(WARN_CONFIG_CONFLICTING_DEFINITIONS_IN_SCHEMA_FILE, schemaFile, e.getMessageObject());
+        try
+        {
+          updateSchema(schema, schemaEntry, true);
+        }
+        catch (DirectoryException e2)
+        {
+          // This should never happen
+          logger.traceException(e2);
+        }
+      }
+      else
+      {
+        reportError(failOnError, e,
+            WARN_CONFIG_SCHEMA_CANNOT_PARSE_DEFINITIONS_IN_SCHEMA_FILE.get(schemaFile, e.getMessageObject()));
+      }
+    }
+  }
+
+  private static Entry readSchemaEntryFromFile(String schemaFile, boolean failOnError)
+      throws ConfigException, InitializationException
   {
     // Create an LDIF reader to use when reading the files.
     String schemaDirPath = getSchemaDirectoryPath();
@@ -359,15 +431,12 @@
       {
         throw new ConfigException(message);
       }
-      else
-      {
-        logger.error(message);
-        return null;
-      }
+      logger.error(message);
+      return null;
     }
 
     // Read the LDIF entry from the file and close the file.
-    Entry entry;
+    final Entry entry;
     try
     {
       entry = reader.readEntry(false);
@@ -376,7 +445,7 @@
       {
         // The file was empty -- skip it.
         reader.close();
-        return new LinkedList<>();
+        return null;
       }
     }
     catch (Exception e)
@@ -390,12 +459,9 @@
       {
         throw new InitializationException(message, e);
       }
-      else
-      {
-        logger.error(message);
-        StaticUtils.close(reader);
-        return null;
-      }
+      logger.error(message);
+      StaticUtils.close(reader);
+      return null;
     }
 
     // If there are any more entries in the file, then print a warning message.
@@ -417,147 +483,36 @@
     {
       StaticUtils.close(reader);
     }
+    return entry;
+  }
 
-    // Get the attributeTypes attribute from the entry.
-    List<Modification> mods = new LinkedList<>();
-
-    //parse the syntaxes first because attributes rely on these.
-    List<Attribute> ldapSyntaxList = getLdapSyntaxesAttributes(schema, entry, mods);
-    List<Attribute> attrList = getAttributeTypeAttributes(schema, entry, mods);
-    List<Attribute> ocList = getObjectClassesAttributes(schema, entry, mods);
-    List<Attribute> nfList = getNameFormsAttributes(schema, entry, mods);
-    List<Attribute> dcrList = getDITContentRulesAttributes(schema, entry, mods);
-    List<Attribute> dsrList = getDITStructureRulesAttributes(schema, entry, mods);
-    List<Attribute> mruList = getMatchingRuleUsesAttributes(schema, entry, mods);
-
-    // Loop on all the attribute of the schema entry to
-    // find the extra attribute that should be loaded in the Schema.
-    for (Attribute attribute : entry.getAttributes())
+  private static void updateSchema(Schema schema, final org.forgerock.opendj.ldap.Entry schemaEntry,
+      final boolean overwrite) throws DirectoryException
+  {
+    schema.updateSchema(new SchemaUpdater()
     {
-      if (!isSchemaAttribute(attribute))
+      @Override
+      public org.forgerock.opendj.ldap.schema.Schema update(SchemaBuilder builder)
       {
-        schema.addExtraAttribute(attribute.getAttributeDescription().getNameOrOID(), attribute);
+        return builder.addSchema(schemaEntry, overwrite).toSchema();
+      }
+    });
+  }
+
+  private static List<Modification> createAddModifications(Entry entry,  AttributeType... attrTypes)
+  {
+    int nbMods = entry.getUserAttributes().size() + entry.getOperationalAttributes().size();
+    List<Modification> mods = new ArrayList<>(nbMods);
+    for (AttributeType attrType : attrTypes)
+    {
+      for (Attribute a : entry.getAttribute(attrType))
+      {
+        mods.add(new Modification(ModificationType.ADD, a));
       }
     }
-
-    parseLdapSyntaxesDefinitions(schema, schemaFile, failOnError, ldapSyntaxList);
-    parseAttributeTypeDefinitions(schema, schemaFile, failOnError, attrList);
-    parseObjectclassDefinitions(schema, schemaFile, failOnError, ocList);
-    parseNameFormDefinitions(schema, schemaFile, failOnError, nfList);
-    parseDITContentRuleDefinitions(schema, schemaFile, failOnError, dcrList);
-    parseDITStructureRuleDefinitions(schema, schemaFile, failOnError, dsrList);
-    parseMatchingRuleUseDefinitions(schema, schemaFile, failOnError, mruList);
-
     return mods;
   }
 
-  private static List<Attribute> getLdapSyntaxesAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_LDAP_SYNTAX_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getLDAPSyntaxDescriptionSyntax();
-    }
-
-    AttributeType ldapSyntaxAttrType = schema.getAttributeType(ATTR_LDAP_SYNTAXES, syntax);
-    return createAddModifications(entry, mods, ldapSyntaxAttrType);
-  }
-
-  private static List<Attribute> getAttributeTypeAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getAttributeTypeDescriptionSyntax();
-    }
-    AttributeType attributeAttrType = schema.getAttributeType(ATTR_ATTRIBUTE_TYPES, syntax);
-    return createAddModifications(entry, mods, attributeAttrType);
-  }
-
-  /** Get the objectClasses attribute from the entry. */
-  private static List<Attribute> getObjectClassesAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_OBJECTCLASS_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getObjectClassDescriptionSyntax();
-    }
-    AttributeType objectclassAttrType = schema.getAttributeType(ATTR_OBJECTCLASSES, syntax);
-    return createAddModifications(entry, mods, objectclassAttrType);
-  }
-
-  /** Get the name forms attribute from the entry. */
-  private static List<Attribute> getNameFormsAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_NAME_FORM_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getNameFormDescriptionSyntax();
-    }
-    AttributeType nameFormAttrType = schema.getAttributeType(ATTR_NAME_FORMS, syntax);
-    return createAddModifications(entry, mods, nameFormAttrType);
-  }
-
-  /** Get the DIT content rules attribute from the entry. */
-  private static List<Attribute> getDITContentRulesAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_DIT_CONTENT_RULE_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getDITContentRuleDescriptionSyntax();
-    }
-    AttributeType dcrAttrType = schema.getAttributeType(ATTR_DIT_CONTENT_RULES, syntax);
-    return createAddModifications(entry, mods, dcrAttrType);
-  }
-
-  /** Get the DIT structure rules attribute from the entry. */
-  private static List<Attribute> getDITStructureRulesAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getDITStructureRuleDescriptionSyntax();
-    }
-    AttributeType dsrAttrType = schema.getAttributeType(ATTR_DIT_STRUCTURE_RULES, syntax);
-    return createAddModifications(entry, mods, dsrAttrType);
-  }
-
-  /** Get the matching rule uses attribute from the entry. */
-  private static List<Attribute> getMatchingRuleUsesAttributes(Schema schema,
-      Entry entry, List<Modification> mods) throws ConfigException,
-      InitializationException
-  {
-    Syntax syntax = schema.getSyntax(SYNTAX_MATCHING_RULE_USE_OID);
-    if (syntax == null)
-    {
-      syntax = CoreSchema.getMatchingRuleUseDescriptionSyntax();
-    }
-    AttributeType mruAttrType = schema.getAttributeType(ATTR_MATCHING_RULE_USE, syntax);
-    return createAddModifications(entry, mods, mruAttrType);
-  }
-
-  private static List<Attribute> createAddModifications(Entry entry,
-      List<Modification> mods, AttributeType attrType)
-  {
-    List<Attribute> attributes = entry.getAttribute(attrType);
-    for (Attribute a : attributes)
-    {
-      mods.add(new Modification(ModificationType.ADD, a));
-    }
-    return attributes;
-  }
-
   /** Parse the ldapsyntaxes definitions if there are any. */
   private static void parseLdapSyntaxesDefinitions(Schema schema,
       String schemaFile, boolean failOnError, List<Attribute> ldapSyntaxList)
@@ -603,166 +558,6 @@
     }
   }
 
-  /** Parse the attribute type definitions if there are any. */
-  private static void parseAttributeTypeDefinitions(
-      Schema schema, String schemaFile, boolean failOnError, List<Attribute> attrList)
-          throws ConfigException
-  {
-    List<String> definitions = toStrings(attrList);
-    try
-    {
-      schema.registerAttributeTypes(definitions, schemaFile, !failOnError);
-    }
-    catch (DirectoryException de)
-    {
-      logger.traceException(de);
-
-      if (de.getResultCode().equals(ResultCode.CONSTRAINT_VIOLATION))
-      {
-        // Register it with the schema. We will allow duplicates, with the
-        // later definition overriding any earlier definition, but we want
-        // to trap them and log a warning.
-        logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_ATTR_TYPE, schemaFile, de.getMessageObject());
-        try
-        {
-          schema.registerAttributeTypes(definitions, schemaFile, true);
-        }
-        catch (DirectoryException e)
-        {
-          // This should never happen
-          logger.traceException(e);
-        }
-      }
-      else
-      {
-        LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get(schemaFile, de.getMessageObject());
-        reportError(failOnError, de, message);
-      }
-    }
-  }
-
-  /** Parse the objectclass definitions if there are any. */
-  private static void parseObjectclassDefinitions(Schema schema,
-      String schemaFile, boolean failOnError, List<Attribute> ocList)
-      throws ConfigException
-  {
-    List<String> definitions = toStrings(ocList);
-    try
-    {
-      schema.registerObjectClasses(definitions, schemaFile, !failOnError);
-    }
-    catch (DirectoryException de)
-    {
-      logger.traceException(de);
-
-      if (de.getResultCode().equals(ResultCode.CONSTRAINT_VIOLATION))
-      {
-        // Register it with the schema. We will allow duplicates, with the
-        // later definition overriding any earlier definition, but we want
-        // to trap them and log a warning.
-        logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_OC, schemaFile, de.getMessageObject());
-        try
-        {
-          schema.registerObjectClasses(definitions, schemaFile, true);
-        }
-        catch (DirectoryException e)
-        {
-          // This should never happen
-          logger.traceException(e);
-        }
-      }
-      else
-      {
-        LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get(schemaFile, de.getMessageObject());
-        reportError(failOnError, de, message);
-      }
-    }
-  }
-
-  private static List<String> toStrings(List<Attribute> attributes)
-  {
-    List<String> results = new ArrayList<>();
-    for (Attribute attr : attributes)
-    {
-      for (ByteString v : attr)
-      {
-        results.add(v.toString());
-      }
-    }
-    return results;
-  }
-
-  /** Parse the name form definitions if there are any. */
-  private static void parseNameFormDefinitions(Schema schema,
-      String schemaFile, boolean failOnError, List<Attribute> nfList)
-      throws ConfigException
-  {
-    for (Attribute a : nfList)
-    {
-      for (ByteString v : a)
-      {
-        // Register it with the schema. We will allow duplicates, with the
-        // later definition overriding any earlier definition, but we want
-        // to trap them and log a warning.
-        String definition = v.toString();
-        try
-        {
-          schema.registerNameForm(definition, schemaFile, failOnError);
-        }
-        catch (DirectoryException de)
-        {
-          logger.traceException(de);
-
-          logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_NAME_FORM, schemaFile, de.getMessageObject());
-
-          try
-          {
-            schema.registerNameForm(definition, schemaFile, true);
-          }
-          catch (Exception e)
-          {
-            // This should never happen.
-            logger.traceException(e);
-          }
-        }
-      }
-    }
-  }
-
-  /** Parse the DIT content rule definitions if there are any. */
-  private static void parseDITContentRuleDefinitions(Schema schema,
-      String schemaFile, boolean failOnError, List<Attribute> dcrList)
-      throws ConfigException
-  {
-    for (Attribute a : dcrList)
-    {
-      for (ByteString v : a)
-      {
-        final String definition = v.toString();
-        try
-        {
-          schema.registerDITContentRule(definition, schemaFile, failOnError);
-        }
-        catch (DirectoryException de)
-        {
-          logger.traceException(de);
-
-          logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DCR, schemaFile, de.getMessageObject());
-
-          try
-          {
-            schema.registerDITContentRule(definition, schemaFile, true);
-          }
-          catch (Exception e)
-          {
-            // This should never happen.
-            logger.traceException(e);
-          }
-        }
-      }
-    }
-  }
-
   private static void reportError(boolean failOnError, Exception e,
       LocalizableMessage message) throws ConfigException
   {
@@ -773,80 +568,6 @@
     logger.error(message);
   }
 
-  /** Parse the DIT structure rule definitions if there are any. */
-  private static void parseDITStructureRuleDefinitions(Schema schema,
-      String schemaFile, boolean failOnError, List<Attribute> dsrList)
-      throws ConfigException
-  {
-    for (Attribute a : dsrList)
-    {
-      for (ByteString v : a)
-      {
-        // Register it with the schema. We will allow duplicates, with the
-        // later definition overriding any earlier definition, but we want
-        // to trap them and log a warning.
-        String definition = v.toString();
-        try
-        {
-          schema.registerDITStructureRule(definition, schemaFile, failOnError);
-        }
-        catch (DirectoryException de)
-        {
-          logger.traceException(de);
-
-          logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DSR, schemaFile, de.getMessageObject());
-
-          try
-          {
-            schema.registerDITStructureRule(definition, schemaFile, true);
-          }
-          catch (Exception e)
-          {
-            // This should never happen.
-            logger.traceException(e);
-          }
-        }
-      }
-    }
-  }
-
-  /** Parse the matching rule use definitions if there are any. */
-  private static void parseMatchingRuleUseDefinitions(Schema schema,
-      String schemaFile, boolean failOnError, List<Attribute> mruList)
-      throws ConfigException
-  {
-    for (Attribute a : mruList)
-    {
-      for (ByteString v : a)
-      {
-        // Register it with the schema. We will allow duplicates, with the
-        // later definition overriding any earlier definition, but we want
-        // to trap them and log a warning.
-        String definition = v.toString();
-        try
-        {
-          schema.registerMatchingRuleUse(definition, schemaFile, failOnError);
-        }
-        catch (DirectoryException de)
-        {
-          logger.traceException(de);
-
-          logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_MRU, schemaFile, de.getMessageObject());
-
-          try
-          {
-            schema.registerMatchingRuleUse(definition, schemaFile, true);
-          }
-          catch (Exception e)
-          {
-            // This should never happen.
-            logger.traceException(e);
-          }
-        }
-      }
-    }
-  }
-
   /**
    * This method checks if a given attribute is an attribute that
    * is used by the definition of the schema.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java b/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
index f499920..0694161 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
@@ -62,13 +62,11 @@
   /** The list of files to be added to the server schema. */
   private TreeSet<String> filesToAdd;
 
-  /** {@inheritDoc} */
   @Override
   public LocalizableMessage getDisplayName() {
     return INFO_TASK_ADD_SCHEMA_FILE_NAME.get();
   }
 
-  /** {@inheritDoc} */
   @Override
   public void initializeTask()
          throws DirectoryException
@@ -87,7 +85,6 @@
       }
     }
 
-
     // Get the attribute that specifies which schema file(s) to add.
     Entry taskEntry = getTaskEntry();
     AttributeType attrType = DirectoryServer.getAttributeType(ATTR_TASK_ADDSCHEMAFILE_FILENAME);
@@ -99,7 +96,6 @@
       throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
     }
 
-
     // Get the name(s) of the schema files to add and make sure they exist in
     // the schema directory.
     String schemaInstanceDirectory =
@@ -136,7 +132,6 @@
       }
     }
 
-
     // Create a new dummy schema and make sure that we can add the contents of
     // all the schema files into it.  Even though this duplicates work we'll
     // have to do later, it will be good to do it now as well so we can reject
@@ -159,9 +154,6 @@
     }
   }
 
-
-
-  /** {@inheritDoc} */
   @Override
   protected TaskState runTask()
   {
@@ -182,7 +174,7 @@
       {
         try
         {
-          List<Modification> modList = SchemaConfigManager.loadSchemaFile(schema, schemaFile);
+          List<Modification> modList = SchemaConfigManager.loadSchemaFileReturnModifications(schema, schemaFile);
           for (Modification m : modList)
           {
             Attribute a = m.getAttribute();
@@ -234,4 +226,3 @@
     }
   }
 }
-
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
index bfbad7a..146badd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
@@ -33,7 +33,6 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.text.ParseException;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -411,50 +410,6 @@
   }
 
   /**
-   * Registers a list of attribute types from their provided definitions.
-   * <p>
-   * This method allows to do only one schema change for multiple definitions,
-   * thus avoiding the cost (and the issue of stale schema references) of rebuilding a new schema for each definition.
-   *
-   * @param definitions
-   *          The definitions of the attribute types
-   * @param schemaFile
-   *          The schema file where these definitions belong, can be {@code null}
-   * @param overwrite
-   *          Indicates whether to overwrite the attribute
-   *          type if it already exists based on OID or name
-   * @throws DirectoryException
-   *            If an error occurs
-   */
-  public void registerAttributeTypes(final List<String> definitions, final String schemaFile, final boolean overwrite)
-      throws DirectoryException
-  {
-    exclusiveLock.lock();
-    try
-    {
-      SchemaBuilder builder = new SchemaBuilder(schemaNG);
-      for (String definition : definitions)
-      {
-        String defWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-        builder.addAttributeType(defWithFile, overwrite);
-      }
-      switchSchema(builder.toSchema());
-    }
-    catch (ConflictingSchemaElementException | UnknownSchemaElementException e)
-    {
-      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
-    }
-    catch (LocalizedIllegalArgumentException e)
-    {
-      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
-    }
-    finally
-    {
-      exclusiveLock.unlock();
-    }
-  }
-
-  /**
    * Registers an attribute type from its provided definition.
    *
    * @param definition
@@ -471,7 +426,26 @@
   public void registerAttributeType(final String definition, final String schemaFile, final boolean overwrite)
       throws DirectoryException
   {
-    registerAttributeTypes(Arrays.asList(definition), schemaFile, overwrite);
+    exclusiveLock.lock();
+    try
+    {
+      String defWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
+      switchSchema(new SchemaBuilder(schemaNG)
+          .addAttributeType(defWithFile, overwrite)
+          .toSchema());
+    }
+    catch (ConflictingSchemaElementException | UnknownSchemaElementException e)
+    {
+      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
+    }
+    catch (LocalizedIllegalArgumentException e)
+    {
+      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+    }
+    finally
+    {
+      exclusiveLock.unlock();
+    }
   }
 
   /**
@@ -743,34 +717,28 @@
   }
 
   /**
-   * Registers a list of object classes from their provided definitions.
-   * <p>
-   * This method allows to do only one schema change for multiple definitions,
-   * thus avoiding the cost (and the issue of stale schema references) of rebuilding a new schema for each definition.
+   * Registers an object class from its provided definition.
    *
-   * @param definitions
-   *          The definitions of the object classes
+   * @param definition
+   *          The definition of the object class
    * @param schemaFile
-   *          The schema file where these definitions belong, can be {@code null}
-   * @param overwrite
-   *          Indicates whether to overwrite the attribute
-   *          type if it already exists based on OID or name
+   *          The schema file where this definition belongs, may be {@code null}
+   * @param overwriteExisting
+   *          Indicates whether to overwrite the object class
+   *          if it already exists based on OID or name
    * @throws DirectoryException
    *            If an error occurs
    */
-  public void registerObjectClasses(final List<String> definitions, final String schemaFile, final boolean overwrite)
+  public void registerObjectClass(String definition, String schemaFile, boolean overwriteExisting)
       throws DirectoryException
   {
     exclusiveLock.lock();
     try
     {
-      SchemaBuilder builder = new SchemaBuilder(schemaNG);
-      for (String definition : definitions)
-      {
-        String defWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-        builder.addObjectClass(defWithFile, overwrite);
-      }
-      switchSchema(builder.toSchema());
+      String defWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
+      switchSchema(new SchemaBuilder(schemaNG)
+          .addObjectClass(defWithFile, overwriteExisting)
+          .toSchema());
     }
     catch (ConflictingSchemaElementException | UnknownSchemaElementException e)
     {
@@ -1249,37 +1217,6 @@
     }
   }
 
-  /**
-   * Registers the provided matching rule use definition with this schema.
-   *
-   * @param definition
-   *          The matching rule use definition to register.
-   * @param schemaFile
-   *          The schema file where this definition belongs, maybe {@code null}
-   * @param overwriteExisting
-   *          Indicates whether to overwrite an existing mapping if there are any conflicts (i.e.,
-   *          another matching rule use with the same matching rule).
-   * @throws DirectoryException
-   *           If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
-   *           {@code false}
-   */
-  public void registerMatchingRuleUse(String definition, String schemaFile, boolean overwriteExisting)
-      throws DirectoryException
-  {
-    exclusiveLock.lock();
-    try
-    {
-      String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-      switchSchema(new SchemaBuilder(schemaNG)
-        .addMatchingRuleUse(definitionWithFile, overwriteExisting)
-        .toSchema());
-    }
-    finally
-    {
-      exclusiveLock.unlock();
-    }
-  }
-
   private String getDefinitionWithSchemaFile(String definition, String schemaFile)
   {
     return schemaFile != null ? addSchemaFileToElementDefinitionIfAbsent(definition, schemaFile) : definition;
@@ -1381,37 +1318,6 @@
   }
 
   /**
-   * Registers the provided DIT content rule definition with this schema.
-   *
-   * @param definition
-   *          The DIT content rule definition to register.
-   * @param schemaFile
-   *          The schema file where this definition belongs, maybe {@code null}
-   * @param overwriteExisting
-   *          Indicates whether to overwrite an existing mapping if there are any conflicts (i.e.,
-   *          another DIT content rule with the same object class).
-   * @throws DirectoryException
-   *           If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
-   *           {@code false}
-   */
-  public void registerDITContentRule(String definition, String schemaFile, boolean overwriteExisting)
-      throws DirectoryException
-  {
-    exclusiveLock.lock();
-    try
-    {
-      String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-      switchSchema(new SchemaBuilder(schemaNG)
-        .addDITContentRule(definitionWithFile, overwriteExisting)
-        .toSchema());
-    }
-    finally
-    {
-      exclusiveLock.unlock();
-    }
-  }
-
-  /**
    * Deregisters the provided DIT content rule definition with this
    * schema.
    *
@@ -1525,37 +1431,6 @@
   }
 
   /**
-   * Registers the provided DIT structure rule definition with this schema.
-   *
-   * @param definition
-   *          The definition of the DIT structure rule to register.
-   * @param schemaFile
-   *          The schema file where this definition belongs, maybe {@code null}
-   * @param overwriteExisting
-   *          Indicates whether to overwrite an existing mapping if there are any conflicts
-   *          (i.e., another DIT structure rule with the same name form).
-   * @throws DirectoryException
-   *           If a conflict is encountered and the {@code overwriteExisting} flag is set to
-   *           {@code false}
-   */
-  public void registerDITStructureRule(String definition, String schemaFile, boolean overwriteExisting)
-      throws DirectoryException
-  {
-    exclusiveLock.lock();
-    try
-    {
-      String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-      switchSchema(new SchemaBuilder(schemaNG)
-          .addDITStructureRule(definitionWithFile, overwriteExisting)
-          .toSchema());
-    }
-    finally
-    {
-      exclusiveLock.unlock();
-    }
-  }
-
-  /**
    * Deregisters the provided DIT structure rule definition with this schema.
    *
    * @param ditStructureRule
@@ -1563,8 +1438,7 @@
    * @throws DirectoryException
    *           If an error occurs.
    */
-  public void deregisterDITStructureRule(
-      DITStructureRule ditStructureRule) throws DirectoryException
+  public void deregisterDITStructureRule(DITStructureRule ditStructureRule) throws DirectoryException
   {
     exclusiveLock.lock();
     try
@@ -1680,36 +1554,6 @@
   }
 
   /**
-   * Registers the provided name form definition with this schema.
-   *
-   * @param definition
-   *          The name form definition to register.
-   * @param schemaFile
-   *          The schema file where this definition belongs, maybe {@code null}
-   * @param overwriteExisting
-   *          Indicates whether to overwrite an existing mapping if there are any conflicts
-   * @throws DirectoryException
-   *           If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
-   *           {@code false}
-   */
-  public void registerNameForm(String definition, String schemaFile, boolean overwriteExisting)
-      throws DirectoryException
-  {
-    exclusiveLock.lock();
-    try
-    {
-      String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
-      switchSchema(new SchemaBuilder(schemaNG)
-        .addNameForm(definitionWithFile, overwriteExisting)
-        .toSchema());
-    }
-    finally
-    {
-      exclusiveLock.unlock();
-    }
-  }
-
-  /**
    * Deregisters the provided name form definition with this schema.
    *
    * @param  nameForm  The name form definition to deregister.
@@ -1793,25 +1637,6 @@
   }
 
   /**
-   * Registers an object class from its provided definition.
-   *
-   * @param definition
-   *          The definition of the object class
-   * @param schemaFile
-   *          The schema file where this definition belongs, may be {@code null}
-   * @param overwriteExisting
-   *          Indicates whether to overwrite the object class
-   *          if it already exists based on OID or name
-   * @throws DirectoryException
-   *            If an error occurs
-   */
-  public void registerObjectClass(String definition, String schemaFile, boolean overwriteExisting)
-      throws DirectoryException
-  {
-    registerObjectClasses(Collections.singletonList(definition), schemaFile, overwriteExisting);
-  }
-
-  /**
    * Creates a new {@link Schema} object that is a duplicate of this one. It elements may be added
    * and removed from the duplicate without impacting this version.
    *
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/config.properties b/opendj-server-legacy/src/messages/org/opends/messages/config.properties
index f8709b7..6e71327 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/config.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/config.properties
@@ -270,6 +270,11 @@
 WARN_CONFIG_SCHEMA_MR_CONFLICTING_MR_173=The matching rule defined in \
  configuration entry %s conflicts with another matching rule defined in the \
  server configuration: %s. This matching rule will not be used
+WARN_CONFIG_CONFLICTING_DEFINITIONS_IN_SCHEMA_FILE_174=One or several \
+ definitions read from schema configuration file %s conflict with other \
+ definitions already read into the schema: %s. The later definitions will be used
+WARN_CONFIG_SCHEMA_CANNOT_PARSE_DEFINITIONS_IN_SCHEMA_FILE_175=Unable to parse \
+ the definitions from schema configuration file %s: %s
 ERR_CONFIG_SCHEMA_SYNTAX_CANNOT_INITIALIZE_186=An error occurred while \
  trying to initialize an attribute syntax loaded from class %s with the \
  information in configuration entry %s: %s. This syntax will be disabled
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/tasks/AddSchemaFileTaskTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/tasks/AddSchemaFileTaskTestCase.java
index c29cfd7..a28f211 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/tasks/AddSchemaFileTaskTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/tasks/AddSchemaFileTaskTestCase.java
@@ -20,7 +20,11 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.schema.CoreSchema;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.opendj.ldap.schema.Schema;
 import org.forgerock.opendj.ldap.schema.SchemaBuilder;
@@ -28,8 +32,8 @@
 import org.opends.server.backends.SchemaTestMatchingRuleImpl;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.SchemaConfigManager;
-import org.opends.server.schema.SchemaConstants;
-import org.forgerock.opendj.ldap.DN;
+import org.opends.server.types.DirectoryException;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -39,9 +43,11 @@
  * Tests invocation of the import and export tasks, but does not aim to
  * thoroughly test the underlying backend implementations.
  */
-public class AddSchemaFileTaskTestCase
-       extends TasksTestCase
+@SuppressWarnings("javadoc")
+public class AddSchemaFileTaskTestCase extends TasksTestCase
 {
+  private static List<MatchingRule> matchingRulesToRemove = new ArrayList<>();
+
   /**
    * Make sure that the Directory Server is running.
    *
@@ -53,17 +59,29 @@
     TestCaseUtils.startServer();
   }
 
-  private MatchingRule getMatchingRule(String name, String oid, boolean isObsolete)
+  @AfterClass
+  public void deregisterMatchingRules() throws Exception
   {
-    Schema schema =
-        new SchemaBuilder(Schema.getCoreSchema())
-          .buildMatchingRule(oid)
-            .syntaxOID(SchemaConstants.SYNTAX_DIRECTORY_STRING_OID)
-            .names(name)
-            .implementation(new SchemaTestMatchingRuleImpl())
-            .obsolete(isObsolete)
-            .addToSchema().toSchema();
-    return schema.getMatchingRule(oid);
+    for (MatchingRule matchingRule : matchingRulesToRemove)
+    {
+      org.opends.server.types.Schema schema = DirectoryServer.getSchema();
+      schema.deregisterMatchingRuleUse(schema.getMatchingRuleUse(matchingRule));
+      schema.deregisterMatchingRule(matchingRule);
+    }
+  }
+
+  private void registerNewMatchingRule(String name, String oid) throws DirectoryException
+  {
+    MatchingRule matchingRule = new SchemaBuilder(Schema.getCoreSchema())
+        .buildMatchingRule(oid)
+        .syntaxOID(CoreSchema.getDirectoryStringSyntax().getOID())
+        .names(name)
+        .implementation(new SchemaTestMatchingRuleImpl())
+        .addToSchema()
+        .toSchema()
+        .getMatchingRule(oid);
+    DirectoryServer.getSchema().registerMatchingRule(matchingRule, false);
+    matchingRulesToRemove.add(matchingRule);
   }
 
   /**
@@ -85,8 +103,7 @@
     Thread.sleep(2);
 
 
-    MatchingRule matchingRule = getMatchingRule("testAddValidSchemaFileMatch", "1.3.6.1.4.1.26027.1.999.23", false);
-    DirectoryServer.getSchema().registerMatchingRule(matchingRule, false);
+    registerNewMatchingRule("testAddValidSchemaFileMatch", "1.3.6.1.4.1.26027.1.999.23");
 
 
     String schemaDirectory = SchemaConfigManager.getSchemaDirectoryPath();
@@ -134,8 +151,6 @@
                      beforeModifyTimestamp);
   }
 
-
-
   /**
    * Attempts to add multiple new files to the server schema where the files
    * exist and have valid contents.
@@ -154,13 +169,7 @@
               DirectoryServer.getSchema().getYoungestModificationTime();
     Thread.sleep(2);
 
-
-    String schemaDirectory = SchemaConfigManager.getSchemaDirectoryPath();
-
-    MatchingRule matchingRule1 =
-        getMatchingRule("testAddMultipleValidSchemaFiles1Match", "1.3.6.1.4.1.26027.1.999.24", false);
-
-    DirectoryServer.getSchema().registerMatchingRule(matchingRule1, false);
+    registerNewMatchingRule("testAddMultipleValidSchemaFiles1Match", "1.3.6.1.4.1.26027.1.999.24");
 
     String[] fileLines1 =
     {
@@ -187,13 +196,11 @@
            "APPLIES testAddMultipleValidSchemaFiles1AT )"
     };
 
+    String schemaDirectory = SchemaConfigManager.getSchemaDirectoryPath();
     File validFile1 = new File(schemaDirectory, "05-multiple-valid-1.ldif");
     writeLines(validFile1, fileLines1);
 
-
-    MatchingRule matchingRule2 =
-        getMatchingRule("testAddMultipleValidSchemaFiles2Match", "1.3.6.1.4.1.26027.1.999.25", false);
-    DirectoryServer.getSchema().registerMatchingRule(matchingRule2, false);
+    registerNewMatchingRule("testAddMultipleValidSchemaFiles2Match", "1.3.6.1.4.1.26027.1.999.25");
 
     String[] fileLines2 =
     {

--
Gitblit v1.10.0