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

sin
29.43.2009 a0e29bcfe05d737bb1b644d282b2383ee6126bad
issue 3444:Only a single name form allowed per structural object class
6 files modified
390 ■■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java 49 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java 10 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java 19 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/types/Entry.java 194 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/types/Schema.java 108 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java 10 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -1846,14 +1846,19 @@
    // Make sure that the attribute type isn't used as a required or optional
    // attribute type in any name form.
    for (NameForm nf : schema.getNameFormsByObjectClass().values())
    for (List<NameForm> mappedForms :
                      schema.getNameFormsByObjectClass().values())
    {
      if (nf.getRequiredAttributes().contains(removeType) ||
          nf.getOptionalAttributes().contains(removeType))
      for(NameForm nf : mappedForms)
      {
        Message message = ERR_SCHEMA_MODIFY_REMOVE_AT_IN_NF.get(
            removeType.getNameOrOID(), nf.getNameOrOID());
        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
        if (nf.getRequiredAttributes().contains(removeType) ||
            nf.getOptionalAttributes().contains(removeType))
        {
          Message message = ERR_SCHEMA_MODIFY_REMOVE_AT_IN_NF.get(
              removeType.getNameOrOID(), nf.getNameOrOID());
          throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
                  message);
        }
      }
    }
@@ -2158,11 +2163,17 @@
    // Make sure that the objectclass isn't used as the structural class for
    // any name form.
    NameForm nf = schema.getNameForm(removeClass);
    if (nf != null)
    List<NameForm> mappedForms = schema.getNameForm(removeClass);
    if (mappedForms != null)
    {
      StringBuilder buffer = new StringBuilder();
      for(NameForm nf : mappedForms)
      {
        buffer.append(nf.getNameOrOID());
        buffer.append("\t");
      }
      Message message = ERR_SCHEMA_MODIFY_REMOVE_OC_IN_NF.get(
          removeClass.getNameOrOID(), nf.getNameOrOID());
          removeClass.getNameOrOID(), buffer.toString());
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
@@ -2267,15 +2278,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    NameForm existingNFForClass = schema.getNameForm(structuralClass);
    if ((existingNFForClass != null) && (existingNFForClass != existingNF))
    {
      Message message = ERR_SCHEMA_MODIFY_STRUCTURAL_OC_CONFLICT_FOR_ADD_NF.
          get(nameForm.getNameOrOID(), structuralClass.getNameOrOID(),
              existingNFForClass.getNameOrOID());
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    for (AttributeType at : nameForm.getRequiredAttributes())
    {
      if (! schema.hasAttributeType(at.getOID()))
@@ -3345,12 +3347,15 @@
    // is no hierarchical relationship between name forms, we don't need to
    // worry about ordering.
    values = new LinkedHashSet<AttributeValue>();
    for (NameForm nf : schema.getNameFormsByObjectClass().values())
    for (List<NameForm> forms : schema.getNameFormsByObjectClass().values())
    {
      if (schemaFile.equals(nf.getSchemaFile()))
      for(NameForm nf : forms)
      {
        values.add(AttributeValues.create(
            nameFormsType, nf.getDefinition()));
        if (schemaFile.equals(nf.getSchemaFile()))
        {
          values.add(AttributeValues.create(
              nameFormsType, nf.getDefinition()));
        }
      }
    }
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -4435,7 +4435,7 @@
   *
   * @return  The set of name forms defined in the Directory Server.
   */
  public static ConcurrentHashMap<ObjectClass,NameForm> getNameForms()
  public static ConcurrentHashMap<ObjectClass,List<NameForm>> getNameForms()
  {
    return directoryServer.schema.getNameFormsByObjectClass();
  }
@@ -4457,15 +4457,15 @@
  /**
   * Retrieves the name form associated with the specified objectclass.
   * Retrieves the name forms associated with the specified objectclass.
   *
   * @param  objectClass  The objectclass for which to retrieve the associated
   *                      name form.
   *
   * @return  The requested name form, or <CODE>null</CODE> if no such name form
   *          is defined in the schema.
   * @return  The requested name forms, or <CODE>null</CODE> if no such name
   *           form is defined in the schema.
   */
  public static NameForm getNameForm(ObjectClass objectClass)
  public static List<NameForm> getNameForm(ObjectClass objectClass)
  {
    return directoryServer.schema.getNameForm(objectClass);
  }
opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
@@ -22,9 +22,10 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import java.util.List;
import org.opends.messages.Message;
@@ -658,12 +659,12 @@
  /**
   * Retrieves the set of name forms defined in the Directory Server.
   * The mapping will be between the structural objectclass and its
   * corresponding name form.  The returned map must not be altered by
   * the caller.
   * corresponding name forms.  The returned map must not be altered
   * by the caller.
   *
   * @return  The set of name forms defined in the Directory Server.
   */
  public static Map<ObjectClass,NameForm> getNameForms()
  public static Map<ObjectClass,List<NameForm>> getNameForms()
  {
    return DirectoryServer.getNameForms();
  }
@@ -671,16 +672,16 @@
  /**
   * Retrieves the name form associated with the specified structural
   * objectclass.
   * Retrieves the list of name forms associated with the specified
   * structural objectclass.
   *
   * @param  objectClass  The structural objectclass for which to
   *                      retrieve the  associated name form.
   *
   * @return  The requested name form, or <CODE>null</CODE> if no such
   *          name form is defined in the schema.
   * @return  The list of requested name forms, or <CODE>null</CODE>
   *           if no such name form is defined in the schema.
   */
  public static NameForm getNameForm(ObjectClass objectClass)
  public static List<NameForm> getNameForm(ObjectClass objectClass)
  {
    return DirectoryServer.getNameForm(objectClass);
  }
opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
@@ -2052,14 +2052,60 @@
        ditContentRule = null;
      }
      if (! checkAttributesAndObjectClasses(ditContentRule,
                 structuralPolicy, invalidReason))
      {
        return false;
      }
      if (validateNameForms)
      {
        nameForm = DirectoryServer.getNameForm(structuralClass);
        if ((nameForm != null) && nameForm.isObsolete())
        /**
         * There may be multiple nameforms registered with this
         * structural objectclass.However, we need to select only one
         * of the nameforms and its corresponding DITstructure rule.
         * We will iterate over all the nameforms and see if atleast
         * one is acceptable before rejecting the entry.
         * DITStructureRules corresponding to other non-acceptable
         * nameforms are not applied.
         */
        List<NameForm> listForms =
                DirectoryServer.getNameForm(structuralClass);
        if(listForms != null)
        {
          nameForm = null;
          boolean matchFound = false;
          boolean obsolete = true;
          for(int index=0; index <listForms.size(); index++)
          {
            NameForm nf = listForms.get(index);
            if(!nf.isObsolete())
            {
              obsolete = false;
              matchFound = checkNameForm(nf,
                      structuralPolicy, invalidReason);
              if(matchFound)
              {
                nameForm = nf;
                break;
              }
              if(index != listForms.size()-1)
              {
                invalidReason.append(",");
              }
            }
          }
          if(! obsolete && !matchFound)
          {
            //We couldn't match this entry against any of the
            // nameforms.
            return false;
          }
        }
        if (validateStructureRules && (nameForm != null))
        {
          ditStructureRule =
@@ -2074,24 +2120,6 @@
    }
    if (! checkAttributesAndObjectClasses(ditContentRule,
               structuralPolicy, invalidReason))
    {
      return false;
    }
    // If there is a name form for this entry, then make sure that the
    // RDN for the entry is in compliance with it.
    if (nameForm != null)
    {
      if (! checkNameForm(nameForm, structuralPolicy, invalidReason))
      {
        return false;
      }
    }
    // If there is a DIT content rule for this entry, then make sure
    // that the entry is in compliance with it.
    if (ditContentRule != null)
@@ -2304,54 +2332,54 @@
    RDN rdn = dn.getRDN();
    if (rdn != null)
    {
      // Make sure that all the required attributes are present.
      for (AttributeType t : nameForm.getRequiredAttributes())
      {
        if (! rdn.hasAttributeType(t))
        // Make sure that all the required attributes are present.
        for (AttributeType t : nameForm.getRequiredAttributes())
        {
          Message message =
                  ERR_ENTRY_SCHEMA_RDN_MISSING_REQUIRED_ATTR.get(
                    String.valueOf(dn),
                    t.getNameOrOID(),
                    nameForm.getNameOrOID());
          if (! rdn.hasAttributeType(t))
          {
            Message message =
                    ERR_ENTRY_SCHEMA_RDN_MISSING_REQUIRED_ATTR.get(
                      String.valueOf(dn),
                      t.getNameOrOID(),
                      nameForm.getNameOrOID());
          if (structuralPolicy == AcceptRejectWarn.REJECT)
          {
            invalidReason.append(message);
            return false;
            if (structuralPolicy == AcceptRejectWarn.REJECT)
            {
                invalidReason.append(message);
              return false;
            }
            else if (structuralPolicy == AcceptRejectWarn.WARN)
            {
                logError(message);
              }
            }
          }
          else if (structuralPolicy == AcceptRejectWarn.WARN)
          {
            logError(message);
          }
        }
      }
      // Make sure that all attributes in the RDN are allowed.
      int numAVAs = rdn.getNumValues();
      for (int i = 0; i < numAVAs; i++)
      {
        AttributeType t = rdn.getAttributeType(i);
        if (! nameForm.isRequiredOrOptional(t))
        {
          Message message =
                  ERR_ENTRY_SCHEMA_RDN_DISALLOWED_ATTR.get(
                    String.valueOf(dn),
                    t.getNameOrOID(),
                    nameForm.getNameOrOID());
          // Make sure that all attributes in the RDN are allowed.
          int numAVAs = rdn.getNumValues();
          for (int i = 0; i < numAVAs; i++)
          {
            AttributeType t = rdn.getAttributeType(i);
            if (! nameForm.isRequiredOrOptional(t))
            {
              Message message =
                      ERR_ENTRY_SCHEMA_RDN_DISALLOWED_ATTR.get(
                        String.valueOf(dn),
                        t.getNameOrOID(),
                        nameForm.getNameOrOID());
          if (structuralPolicy == AcceptRejectWarn.REJECT)
          {
            invalidReason.append(message);
            return false;
              if (structuralPolicy == AcceptRejectWarn.REJECT)
              {
                  invalidReason.append(message);
                return false;
              }
              else if (structuralPolicy == AcceptRejectWarn.WARN)
              {
                  logError(message);
                }
              }
            }
          }
          else if (structuralPolicy == AcceptRejectWarn.WARN)
          {
            logError(message);
          }
        }
      }
    }
    // If we've gotten here, then things are OK.
    return true;
@@ -2707,27 +2735,33 @@
        }
        else
        {
          NameForm parentNF =
          List<NameForm> allNFs =
               DirectoryServer.getNameForm(parentStructuralClass);
          if ((parentNF != null) && (! parentNF.isObsolete()))
          if(allNFs != null)
          {
            DITStructureRule parentDSR =
                 DirectoryServer.getDITStructureRule(parentNF);
            if ((parentDSR != null) && (! parentDSR.isObsolete()))
            for(NameForm parentNF : allNFs)
            {
              Message message =
                   ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR.get(
                           String.valueOf(dn),
                           String.valueOf(parentEntry.getDN()));
              if ((parentNF != null) && (! parentNF.isObsolete()))
              {
                DITStructureRule parentDSR =
                     DirectoryServer.getDITStructureRule(parentNF);
                if ((parentDSR != null) && (! parentDSR.isObsolete()))
                {
                  Message message =
                       ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR.get(
                               String.valueOf(dn),
                               String.valueOf(parentEntry.getDN()));
              if (structuralPolicy == AcceptRejectWarn.REJECT)
              {
                invalidReason.append(message);
                return false;
              }
              else if (structuralPolicy == AcceptRejectWarn.WARN)
              {
                logError(message);
                  if (structuralPolicy == AcceptRejectWarn.REJECT)
                  {
                    invalidReason.append(message);
                    return false;
                  }
                  else if (structuralPolicy == AcceptRejectWarn.WARN)
                  {
                    logError(message);
                  }
                }
              }
            }
          }
opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
@@ -34,6 +34,7 @@
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -180,9 +181,10 @@
               ditStructureRulesByNameForm;
  // The set of name forms for this schema, mapped between the
  // structural objectclass for the definition and the name form
  // itself.
  private ConcurrentHashMap<ObjectClass,NameForm> nameFormsByOC;
  // structural objectclass for the definition and the list of name
  // forms
  private ConcurrentHashMap<ObjectClass,List<NameForm>>
          nameFormsByOC;
  // The set of name forms for this schema, mapped between the
  // names/OID and the name form itself.
@@ -258,7 +260,8 @@
         new ConcurrentHashMap<Integer,DITStructureRule>();
    ditStructureRulesByNameForm =
         new ConcurrentHashMap<NameForm,DITStructureRule>();
    nameFormsByOC = new ConcurrentHashMap<ObjectClass,NameForm>();
    nameFormsByOC =
            new ConcurrentHashMap<ObjectClass,List<NameForm>>();
    nameFormsByName = new ConcurrentHashMap<String,NameForm>();
    subordinateTypes =
         new ConcurrentHashMap<AttributeType,List<AttributeType>>();
@@ -2590,14 +2593,12 @@
  /**
   * Retrieves the name form definitions for this schema, as a mapping
   * between the objectclass for the name form and the name form
   * itself.  Each name form should only be present once, since its
   * only key is its objectclass.  The contents of the returned
   * mapping must not be altered.
   * between the objectclass for the name forms and the name forms
   * themselves.
   *
   * @return  The name form definitions for this schema.
   */
  public ConcurrentHashMap<ObjectClass,NameForm>
  public ConcurrentHashMap<ObjectClass,List<NameForm>>
              getNameFormsByObjectClass()
  {
    return nameFormsByOC;
@@ -2657,15 +2658,17 @@
  /**
   * Retrieves the name form definition for the specified objectclass.
   * Retrieves the name forms definition for the specified
   * objectclass.
   *
   * @param  objectClass  The objectclass for the name form to
   *                      retrieve.
   *
   * @return  The requested name form, or <CODE>null</CODE> if no name
   *          form is registered with the provided objectClass.
   * @return  The requested name forms, or <CODE>null</CODE> if no
   *           name forms are registered with the provided
   *           objectClass.
   */
  public NameForm getNameForm(ObjectClass objectClass)
  public List<NameForm> getNameForm(ObjectClass objectClass)
  {
    return nameFormsByOC.get(objectClass);
  }
@@ -2708,19 +2711,25 @@
    synchronized (nameFormsByOC)
    {
      ObjectClass objectClass = nameForm.getStructuralClass();
      List<NameForm> mappedForms = nameFormsByOC.get(objectClass);
      if (! overwriteExisting)
      {
        if (nameFormsByOC.containsKey(objectClass))
        if(mappedForms !=null)
        {
          NameForm conflictingNameForm =
               nameFormsByOC.get(objectClass);
          Message message = ERR_SCHEMA_CONFLICTING_NAME_FORM_OC.
              get(nameForm.getNameOrOID(), objectClass.getNameOrOID(),
                  conflictingNameForm.getNameOrOID());
          throw new DirectoryException(
                         ResultCode.CONSTRAINT_VIOLATION, message);
          //Iterate over the forms to make sure we aren't adding a
          //duplicate.
          for(NameForm nf : mappedForms)
          {
            if(nf.equals(nameForm))
            {
              Message message = ERR_SCHEMA_CONFLICTING_NAME_FORM_OC.
                get(nameForm.getNameOrOID(),
                    objectClass.getNameOrOID(),
                    nf.getNameOrOID());
              throw new DirectoryException(
                           ResultCode.CONSTRAINT_VIOLATION, message);
            }
          }
        }
        String oid = toLowerCase(nameForm.getOID());
@@ -2750,7 +2759,13 @@
        }
      }
      nameFormsByOC.put(objectClass, nameForm);
      if(mappedForms == null)
      {
        mappedForms = new ArrayList<NameForm>();
      }
      mappedForms.add(nameForm);
      nameFormsByOC.put(objectClass, mappedForms);
      nameFormsByName.put(toLowerCase(nameForm.getOID()), nameForm);
      for (String name : nameForm.getNames().keySet())
@@ -2781,6 +2796,16 @@
  {
    synchronized (nameFormsByOC)
    {
      List<NameForm> mappedForms = nameFormsByOC.get(
              nameForm.getStructuralClass());
      if(mappedForms != null)
      {
        mappedForms.remove(nameForm);
        if(mappedForms.size() == 0)
        {
          nameFormsByOC.remove(nameForm.getStructuralClass());
        }
      }
      nameFormsByOC.remove(nameForm.getStructuralClass(), nameForm);
      nameFormsByName.remove(toLowerCase(nameForm.getOID()),
                             nameForm);
@@ -3006,15 +3031,18 @@
        }
      }
      for (NameForm nf : nameFormsByOC.values())
      for (List<NameForm> mappedForms : nameFormsByOC.values())
      {
        if (nf.getRequiredAttributes().contains(t) ||
            nf.getOptionalAttributes().contains(t))
        for(NameForm nf : mappedForms)
        {
          NameForm newNF = nf.recreateFromDefinition();
          deregisterNameForm(nf);
          registerNameForm(newNF, true);
          rebuildDependentElements(nf, depth+1);
          if (nf.getRequiredAttributes().contains(t) ||
              nf.getOptionalAttributes().contains(t))
          {
            NameForm newNF = nf.recreateFromDefinition();
            deregisterNameForm(nf);
            registerNameForm(newNF, true);
            rebuildDependentElements(nf, depth+1);
          }
        }
      }
@@ -3058,13 +3086,19 @@
        }
      }
      NameForm nf = nameFormsByOC.get(c);
      if (nf != null)
      List<NameForm> mappedForms = nameFormsByOC.get(c);
      if(mappedForms != null)
      {
        NameForm newNF = nf.recreateFromDefinition();
        deregisterNameForm(nf);
        registerNameForm(newNF, true);
        rebuildDependentElements(nf, depth+1);
        for(NameForm nf : mappedForms)
        {
          if (nf != null)
          {
            NameForm newNF = nf.recreateFromDefinition();
            deregisterNameForm(nf);
            registerNameForm(newNF, true);
            rebuildDependentElements(nf, depth+1);
          }
        }
      }
      for (DITContentRule dcr : ditContentRules.values())
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.backends;
@@ -2923,8 +2923,8 @@
      "-f", path
    };
    assertFalse(LDAPModify.mainModify(args, false, null, null) == 0);
    assertFalse(DirectoryServer.getSchema().hasNameForm(nameFormName));
    assertTrue(LDAPModify.mainModify(args, false, null, null) == 0);
    assertTrue(DirectoryServer.getSchema().hasNameForm(nameFormName));
  }
@@ -5405,7 +5405,7 @@
  {
    File tempFile = File.createTempFile("schema", "testImportLDIF");
    tempFile.deleteOnExit();
    LDIFExportConfig exportConfig =
      new LDIFExportConfig(tempFile.getAbsolutePath(),
                           ExistingFileBehavior.OVERWRITE);
@@ -5414,7 +5414,7 @@
    LDIFImportConfig importConfig =
         new LDIFImportConfig(tempFile.getAbsolutePath());
    schemaBackend.importLDIF(importConfig);
  }