From 1a9cf8eb5d85975f405a129743de69e56a91334e Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 01 Jul 2016 12:53:43 +0000
Subject: [PATCH] OPENDJ-2956 Issue warnings during schema validation of a name form if it references obsolete elements

---
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java         |   29 +++++++++-----
 opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java |   30 ---------------
 opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties         |    5 ++
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java    |    2 
 4 files changed, 25 insertions(+), 41 deletions(-)

diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
index b98fb2b..214bb0c 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
@@ -16,10 +16,7 @@
  */
 package org.forgerock.opendj.ldap.schema;
 
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_NAME_FORM_STRUCTURAL_CLASS_NOT_STRUCTURAL1;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR1;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR1;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_STRUCTURAL_CLASS1;
+import static com.forgerock.opendj.ldap.CoreMessages.*;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -591,7 +588,7 @@
         }
     }
 
-    void validate(final Schema schema) throws SchemaException {
+    void validate(final Schema schema, final List<LocalizableMessage> warnings) throws SchemaException {
         try {
             structuralClass = schema.getObjectClass(structuralClassOID);
         } catch (final UnknownSchemaElementException e) {
@@ -607,29 +604,41 @@
                             structuralClass.getNameOrOID(), structuralClass.getObjectClassType());
             throw new SchemaException(message);
         }
+        if (!isObsolete() && structuralClass.isObsolete()) {
+            warnings.add(WARN_NAME_FORM_HAS_OBSOLETE_STRUCTURAL_CLASS.get(getNameOrOID(), structuralClassOID));
+        }
 
         requiredAttributes =
-              getAttributeTypes(schema, requiredAttributeOIDs, ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR1);
+              getAttributeTypes(schema, requiredAttributeOIDs, ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR1,
+                      warnings, WARN_NAME_FORM_HAS_OBSOLETE_REQUIRED_ATTR);
 
         if (!optionalAttributeOIDs.isEmpty()) {
             optionalAttributes =
-                    getAttributeTypes(schema, optionalAttributeOIDs, ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR1);
+                    getAttributeTypes(schema, optionalAttributeOIDs, ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR1,
+                            warnings, WARN_NAME_FORM_HAS_OBSOLETE_OPTIONAL_ATTR);
         }
 
         optionalAttributes = Collections.unmodifiableSet(optionalAttributes);
         requiredAttributes = Collections.unmodifiableSet(requiredAttributes);
     }
 
-    private Set<AttributeType> getAttributeTypes(final Schema schema, Set<String> oids, Arg2<Object, Object> errorMsg)
+    private Set<AttributeType> getAttributeTypes(final Schema schema, Set<String> oids,
+            Arg2<Object, Object> unknownElementErrorMsg, final List<LocalizableMessage> warnings,
+            Arg2<Object, Object> obsoleteElementMsg)
             throws SchemaException {
         Set<AttributeType> attrTypes = new HashSet<>(oids.size());
         for (final String oid : oids) {
+            AttributeType attributeType;
             try {
-                attrTypes.add(schema.getAttributeType(oid));
+                attributeType = schema.getAttributeType(oid);
+                attrTypes.add(attributeType);
             } catch (final UnknownSchemaElementException e) {
                 // This isn't good because it means that the name form requires
                 // an attribute type that we don't know anything about.
-                throw new SchemaException(errorMsg.get(getNameOrOID(), oid), e);
+                throw new SchemaException(unknownElementErrorMsg.get(getNameOrOID(), oid), e);
+            }
+            if (!isObsolete() && attributeType.isObsolete()) {
+                warnings.add(obsoleteElementMsg.get(getNameOrOID(), oid));
             }
         }
         return attrTypes;
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
index fdfc804..1fc632e 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -2714,7 +2714,7 @@
         for (final NameForm form : numericOID2NameForms.values().toArray(
                 new NameForm[numericOID2NameForms.values().size()])) {
             try {
-                form.validate(schema);
+                form.validate(schema, warnings);
 
                 // build the objectClass2NameForms map
                 final String ocOID = form.getStructuralClass().getOID();
diff --git a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index 2b6f063..c9c96f7 100644
--- a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1633,7 +1633,12 @@
  required attribute type "%s" which is marked as OBSOLETE in the schema
 WARN_OBJECTCLASS_HAS_OBSOLETE_OPTIONAL_ATTR=The object class "%s" specifies the \
  optional attribute type "%s" which is marked as OBSOLETE in the schema
+WARN_NAME_FORM_HAS_OBSOLETE_STRUCTURAL_CLASS=The name form "%s" specifies the \
+ structural object class "%s" which is marked as OBSOLETE in the schema
+WARN_NAME_FORM_HAS_OBSOLETE_REQUIRED_ATTR=The name form "%s" specifies the \
  required attribute type "%s" which is marked as OBSOLETE in the schema
+WARN_NAME_FORM_HAS_OBSOLETE_OPTIONAL_ATTR=The name form "%s" specifies the \
+ optional attribute type "%s" which is marked as OBSOLETE in the schema
 # Labels for generated documentation
 DOC_LOCALE_TAG=Code tag: %s
 DOC_LOCALE_OID=Collation order object identifier: %s
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
index 0bd06de..26e73d6 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
@@ -1405,36 +1405,6 @@
                            Set<String> modifiedSchemaFiles)
           throws DirectoryException
   {
-    // Make sure that the new name form doesn't reference an objectclass
-    // or attributes that are marked OBSOLETE.
-    ObjectClass structuralClass = nameForm.getStructuralClass();
-    if (structuralClass.isObsolete())
-    {
-      LocalizableMessage message = ERR_SCHEMA_MODIFY_NF_OC_OBSOLETE.get(
-          nameForm.getNameOrOID(), structuralClass.getNameOrOID());
-      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
-    }
-
-    for (AttributeType at : nameForm.getRequiredAttributes())
-    {
-      if (at.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_NF_OBSOLETE_REQUIRED_ATTR.get(
-            nameForm.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-      }
-    }
-
-    for (AttributeType at : nameForm.getOptionalAttributes())
-    {
-      if (at.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_NF_OBSOLETE_OPTIONAL_ATTR.get(
-            nameForm.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-      }
-    }
-
     // If there is no existing class, then we're adding a new name form.
     // Otherwise, we're replacing an existing one.
     if (!schema.hasNameForm(nameForm.getNameOrOID()))

--
Gitblit v1.10.0