mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
02.37.2016 a9f305153b30d5cb478c561467803512e90f3ba6
OPENDJ-2647 Schema problems in control-panel

The problem was due to an incremntal update of the SDK schema.
The problem does not appear when the SDK schema is updated in bulk and then built in one go.

SchemaLoader.java:
In getBaseSchema(), use a SchemaBuilder and create the server's schema with a newly built SDK schema.

Schema.java:
In the constructor, validate that the SDK schema has no warnings and throw a DirectoryException if it is has warnings.
This is more consistent with the rest of this class.

SchemaConfigManager.java, DirectoryServer.java:
Handled the newly thrown DirectoryException
5 files modified
177 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/SchemaLoader.java 48 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java 18 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java 32 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java 25 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/schema/LDAPSyntaxTest.java 54 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/SchemaLoader.java
@@ -35,14 +35,17 @@
import java.util.List;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.opends.server.config.ConfigConstants;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.SchemaBuilder;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.opends.server.config.ConfigConstants;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.SchemaConfigManager;
import org.opends.server.schema.SchemaConstants;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ObjectClass;
@@ -189,25 +192,32 @@
   */
  protected Schema getBaseSchema() throws DirectoryException
  {
    // start from default schema
    Schema schema = new Schema(org.forgerock.opendj.ldap.schema.Schema.getDefaultSchema());
    for (MatchingRule mr : matchingRulesToKeep)
    try
    {
      schema.registerMatchingRule(mr, true);
      SchemaBuilder builder = new SchemaBuilder(org.forgerock.opendj.ldap.schema.Schema.getDefaultSchema());
      for (Syntax syntax : syntaxesToKeep)
      {
        builder.buildSyntax(syntax).addToSchemaOverwrite();
      }
      for (MatchingRule mr : matchingRulesToKeep)
      {
        builder.buildMatchingRule(mr).addToSchemaOverwrite();
      }
      for (AttributeType attr : attributesToKeep)
      {
        builder.buildAttributeType(attr).addToSchemaOverwrite();
      }
      Schema schema = new Schema(builder.toSchema());
      for (ObjectClass oc : objectclassesToKeep)
      {
        schema.registerObjectClass(oc, true);
      }
      return schema;
    }
    for (Syntax syntax : syntaxesToKeep)
    catch (LocalizedIllegalArgumentException e)
    {
      schema.registerSyntax(syntax, true);
      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
    }
    for (AttributeType attr : attributesToKeep)
    {
      schema.registerAttributeType(attr, true);
    }
    for (ObjectClass oc : objectclassesToKeep)
    {
      schema.registerObjectClass(oc, true);
    }
    return schema;
  }
  /**
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -890,10 +890,17 @@
      // Set default values for variables that may be needed during schema processing.
      directoryServer.syntaxEnforcementPolicy = AcceptRejectWarn.REJECT;
      // Create the server schema and initialize and register a minimal set of
      // matching rules and attribute syntaxes.
      org.forgerock.opendj.ldap.schema.Schema coreSchema = org.forgerock.opendj.ldap.schema.Schema.getCoreSchema();
      directoryServer.schema = new Schema(coreSchema);
      // Create and initialize the server schema,
      // and register a minimal set of matching rules and attribute syntaxes.
      try
      {
        directoryServer.schema = new Schema(org.forgerock.opendj.ldap.schema.Schema.getCoreSchema());
      }
      catch (DirectoryException unexpected)
      {
        // the core schema should not have any warning
        throw new RuntimeException(unexpected);
      }
      directoryServer.bootstrapAttributeSyntaxes();
      // Perform any additional initialization that might be necessary before
@@ -6843,8 +6850,7 @@
                            theToolDescription, false);
    argParser.setShortToolDescription(REF_SHORT_DESC_START_DS.get());
    // Initialize all the command-line argument types and register them with the
    // parser.
    // Initialize all the command-line argument types and register them with the parser.
    try
    {
      configClass = new StringArgument("configclass", 'C', "configClass",
opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
@@ -42,8 +42,23 @@
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.opends.server.schema.*;
import org.opends.server.types.*;
import org.opends.server.schema.DITContentRuleSyntax;
import org.opends.server.schema.DITStructureRuleSyntax;
import org.opends.server.schema.MatchingRuleUseSyntax;
import org.opends.server.schema.NameFormSyntax;
import org.opends.server.schema.ObjectClassSyntax;
import org.opends.server.types.Attribute;
import org.opends.server.types.DITContentRule;
import org.opends.server.types.DITStructureRule;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.MatchingRuleUse;
import org.opends.server.types.Modification;
import org.opends.server.types.NameForm;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Schema;
import org.opends.server.util.LDIFReader;
import org.opends.server.util.StaticUtils;
@@ -81,9 +96,16 @@
  public SchemaConfigManager(ServerContext serverContext)
  {
    this.serverContext = serverContext;
    // the manager will build the schema from scratch, but we need to start from
    // core schema for SDK schema
    schema = new Schema(org.forgerock.opendj.ldap.schema.Schema.getCoreSchema());
    try
    {
      // the manager will build the schema from scratch, but we need to start from core schema for SDK schema
      schema = new Schema(org.forgerock.opendj.ldap.schema.Schema.getCoreSchema());
    }
    catch (DirectoryException unexpected)
    {
      // the core schema should not have any warning
      throw new RuntimeException(unexpected);
    }
  }
opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
@@ -201,10 +201,12 @@
   *
   * @param schemaNG
   *          The SDK schema
   * @throws DirectoryException
   *           if the schema has warnings
   */
  public Schema(org.forgerock.opendj.ldap.schema.Schema schemaNG)
  public Schema(org.forgerock.opendj.ldap.schema.Schema schemaNG) throws DirectoryException
  {
    setSchemaNG(schemaNG);
    switchSchema(schemaNG);
    objectClasses = new ConcurrentHashMap<String,ObjectClass>();
    matchingRuleUses = new ConcurrentHashMap<MatchingRule,MatchingRuleUse>();
@@ -2022,16 +2024,23 @@
  }
  /**
   * Creates a new <CODE>Schema</CODE> object that is a duplicate of
   * this one.  It elements may be added and removed from the
   * duplicate without impacting this version.
   * 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.
   *
   * @return  A new <CODE>Schema</CODE> object that is a duplicate of
   *          this one.
   * @return A new {@link Schema} object that is a duplicate of this one.
   */
  public Schema duplicate()
  {
    Schema dupSchema = new Schema(schemaNG);
    Schema dupSchema;
    try
    {
      dupSchema = new Schema(schemaNG);
    }
    catch (DirectoryException unexpected)
    {
      // the schema has already been validated
      throw new RuntimeException(unexpected);
    }
    dupSchema.subordinateTypes.putAll(subordinateTypes);
    dupSchema.objectClasses.putAll(objectClasses);
opendj-server-legacy/src/test/java/org/opends/server/schema/LDAPSyntaxTest.java
@@ -22,12 +22,11 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2015 ForgeRock AS
 *      Portions Copyright 2011-2016 ForgeRock AS
 */
package org.opends.server.schema;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.forgerock.opendj.ldap.ByteString;
@@ -51,22 +50,17 @@
import static org.opends.server.protocols.internal.Requests.*;
import static org.testng.Assert.*;
/**
 * Test the LDAPSyntaxDescriptionSyntax.
 */
/** Test the LDAPSyntaxDescriptionSyntax. */
@RemoveOnceSDKSchemaIsUsed
@SuppressWarnings("javadoc")
public class LDAPSyntaxTest extends AttributeSyntaxTest
{
  /** {@inheritDoc} */
  @Override
  protected AttributeSyntax<?> getRule()
  {
    return new LDAPSyntaxDescriptionSyntax();
  }
  /** {@inheritDoc} */
  @Override
  @DataProvider(name="acceptableValues")
  public Object[][] createAcceptableValues()
@@ -172,7 +166,7 @@
        " X-SUBST '1.3.6.1.4.1.1466.115.121.1.15' )");
      //This is not expected to happen
      assertFalse(resultCode==0);
      assertThat(resultCode).isNotEqualTo(0);
      //Test if we can substitute a directory string syntax by an undefined.
      resultCode = TestCaseUtils.applyModifications(true,
@@ -184,11 +178,10 @@
        " X-SUBST '1.1.1' )");
      //This is not expected to happen
      assertFalse(resultCode==0);
      assertThat(resultCode).isNotEqualTo(0);
      //Test if we can substitute a core syntax with a user-defined
      //syntax
      //Test if we can substitute a core syntax with a user-defined syntax
      addSubtitutionSyntax();
      //Replace the IA5Stringsyntax with the custom syntax we just created.
      resultCode = TestCaseUtils.applyModifications(true,
@@ -200,7 +193,7 @@
        " X-SUBST '9.9.9' )");
      //This is not expected to happen
      assertFalse(resultCode==0);
      assertThat(resultCode).isNotEqualTo(0);
    }
    finally
    {
@@ -211,11 +204,9 @@
  /**
    * Tests whether both the virtual and the newly added real substitution
    * sytanx are available when a search is made for ldapsyntaxes attribute.
    *
    * @throws java.lang.Exception
    */
   * Tests whether both the virtual and the newly added real substitution syntax are available when
   * a search is made for ldapsyntaxes attribute.
   */
  @Test
  public void testSubstitutionSyntaxSearch() throws Exception
  {
@@ -229,28 +220,25 @@
      assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
      List<SearchResultEntry> entries = searchOperation.getSearchEntries();
      assertThat(entries).isNotEmpty();
      SearchResultEntry e = entries.get(0);
      //An entry must be returned.
      assertNotNull(e);
      Attribute attr = e.getAttribute("ldapsyntaxes").get(0);
      Iterator<ByteString> iter = attr.iterator();
      //There are other ways of doing it but we will extract the OID
      //from the attribute values and then check to see if our
      //OID is found in the result set or not.
      List<String> syntaxList = new ArrayList<>();
      while(iter.hasNext())
      for (ByteString attrValue : attr)
      {
        //parse the OIDs.
        syntaxList.add(getOIDFromLdapSyntax(iter.next().toString()));
        syntaxList.add(getOIDFromLdapSyntax(attrValue.toString()));
      }
      //Check if we find our OID.
      assertThat(syntaxList).contains("9.9.9");
      //DirectoryString.
      assertThat(syntaxList).contains("1.3.6.1.4.1.1466.115.121.1.15");
      //IA5String.
      assertThat(syntaxList).contains("1.3.6.1.4.1.1466.115.121.1.26");
      assertThat(syntaxList).contains(SchemaConstants.SYNTAX_DIRECTORY_STRING_OID);
      assertThat(syntaxList).contains(SchemaConstants.SYNTAX_IA5_STRING_OID);
    }
    finally
    {
@@ -261,11 +249,9 @@
   /**
    * Tests whether it is possible to add values after an umimplemented syntax
    * has been subsitutited by DirectoryString syntax.
    *
    * @throws java.lang.Exception
    */
   * Tests whether it is possible to add values after an unimplemented syntax has been substituted
   * by DirectoryString syntax.
   */
  @Test
   public void testSubsitutionSyntaxAddValues() throws Exception
   {
@@ -370,9 +356,8 @@
      InternalSearchOperation searchOperation = getRootConnection().processSearch(request);
      assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
      List<SearchResultEntry> entries = searchOperation.getSearchEntries();
      SearchResultEntry e = entries.get(0);
      //An entry must be returned.
      assertNotNull(e);
      assertThat(entries).isNotEmpty();
      assertNotNull(entries.get(0));
    }
    finally
    {
@@ -446,6 +431,7 @@
      InternalSearchOperation searchOperation = getRootConnection().processSearch(request);
      assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
      List<SearchResultEntry> entries = searchOperation.getSearchEntries();
      assertThat(entries).isNotEmpty();
      SearchResultEntry e = entries.get(0);
      //An entry must be returned.
      assertNotNull(e);