From a0e29bcfe05d737bb1b644d282b2383ee6126bad Mon Sep 17 00:00:00 2001
From: sin <sin@localhost>
Date: Wed, 29 Apr 2009 15:43:23 +0000
Subject: [PATCH] issue 3444:Only a single name form allowed per structural object class
---
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java | 10
opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java | 19 +-
opendj-sdk/opends/src/server/org/opends/server/types/Schema.java | 108 ++++++++++-----
opendj-sdk/opends/src/server/org/opends/server/types/Entry.java | 194 ++++++++++++++++-----------
opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java | 49 +++---
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java | 10
6 files changed, 232 insertions(+), 158 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 541eb36..6ffe7f1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/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()));
+ }
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index 2c09046..4e3dd7f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/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);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java b/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
index e8bf2ea..96407c4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
+++ b/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);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java b/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
index c8a22b7..3829f3a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
+++ b/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);
+ }
+ }
}
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java b/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
index 39a448f..fcca6a4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
+++ b/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())
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
index 19249d4..33ed933 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/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);
}
--
Gitblit v1.10.0