From a5e647d27af7f67741546d95eade2595a08b22cd 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 DIT content rule if it references obsolete elements

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java         |   51 -------------------------
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java           |   29 +++++++++++---
 opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java |    4 +-
 opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties                 |   10 +++++
 4 files changed, 34 insertions(+), 60 deletions(-)

diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
index 714ad4f..daa6063 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
@@ -18,7 +18,6 @@
 
 import static com.forgerock.opendj.ldap.CoreMessages.*;
 import static java.util.Arrays.*;
-
 import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
 
 import java.util.Collection;
@@ -784,6 +783,9 @@
                                         .getObjectClassType().toString());
                 warnings.add(message);
             }
+            if (!isObsolete() && structuralClass.isObsolete()) {
+                warnings.add(WARN_DIT_CR_HAS_OBSOLETE_STRUCTURAL_CLASS.get(getNameOrOID(), structuralClassOID));
+            }
         }
 
         if (!auxiliaryClassOIDs.isEmpty()) {
@@ -806,23 +808,29 @@
                                             .toString());
                     throw new SchemaException(message);
                 }
+                if (!isObsolete() && objectClass.isObsolete()) {
+                    warnings.add(WARN_DIT_CR_HAS_OBSOLETE_AUXILIARY_CLASS.get(getNameOrOID(), oid));
+                }
                 auxiliaryClasses.add(objectClass);
             }
         }
 
         if (!requiredAttributeOIDs.isEmpty()) {
             requiredAttributes =
-                getAttributeTypes(schema, requiredAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR1);
+                getAttributeTypes(schema, requiredAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR1,
+                        warnings, WARN_DIT_CR_HAS_OBSOLETE_REQUIRED_ATTR);
         }
 
         if (!optionalAttributeOIDs.isEmpty()) {
             optionalAttributes =
-                getAttributeTypes(schema, optionalAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR1);
+                getAttributeTypes(schema, optionalAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR1,
+                        warnings, WARN_DIT_CR_HAS_OBSOLETE_OPTIONAL_ATTR);
         }
 
         if (!prohibitedAttributeOIDs.isEmpty()) {
             prohibitedAttributes =
-                getAttributeTypes(schema, prohibitedAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR1);
+                getAttributeTypes(schema, prohibitedAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR1,
+                        warnings, WARN_DIT_CR_HAS_OBSOLETE_PROHIBITED_ATTR);
         }
 
         // Make sure that none of the prohibited attributes is required by
@@ -851,16 +859,23 @@
         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> unkwownElementErrorMsg, final List<LocalizableMessage> warnings,
+            Arg2<Object, Object> obsoleteElementWarningMsg)
             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 DIT content rule
                 // requires an attribute type that we don't know anything about.
-                throw new SchemaException(errorMsg.get(getNameOrOID(), oid), e);
+                throw new SchemaException(unkwownElementErrorMsg.get(getNameOrOID(), oid), e);
+            }
+            if (!isObsolete() && attributeType.isObsolete()) {
+                warnings.add(obsoleteElementWarningMsg.get(getNameOrOID(), oid));
             }
         }
         return attrTypes;
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 c9c96f7..92781df 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
@@ -1639,6 +1639,16 @@
  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
+WARN_DIT_CR_HAS_OBSOLETE_STRUCTURAL_CLASS=The DIT content rule "%s" specifies the \
+ structural object class "%s" which is marked as OBSOLETE in the schema
+WARN_DIT_CR_HAS_OBSOLETE_AUXILIARY_CLASS=The DIT content rule "%s" specifies the \
+ auxiliary object class "%s" which is marked as OBSOLETE in the schema
+WARN_DIT_CR_HAS_OBSOLETE_REQUIRED_ATTR=The DIT content rule "%s" specifies the \
+ required attribute type "%s" which is marked as OBSOLETE in the schema
+WARN_DIT_CR_HAS_OBSOLETE_OPTIONAL_ATTR=The DIT content rule "%s" specifies the \
+ optional attribute type "%s" which is marked as OBSOLETE in the schema
+WARN_DIT_CR_HAS_OBSOLETE_PROHIBITED_ATTR=The DIT content rule "%s" specifies the \
+ prohibited 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 26e73d6..d000ce6 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
@@ -1562,57 +1562,6 @@
       }
     }
 
-    ObjectClass structuralClass = ditContentRule.getStructuralClass();
-
-    // Make sure that the new DIT content rule doesn't reference an obsolete
-    // object class or attribute
-    if (structuralClass.isObsolete())
-    {
-      LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_STRUCTURAL_OC_OBSOLETE.get(
-          ditContentRule.getNameOrOID(), structuralClass.getNameOrOID());
-      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-    }
-
-    for (ObjectClass oc : ditContentRule.getAuxiliaryClasses())
-    {
-      if (oc.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_AUXILIARY_OC.get(
-            ditContentRule.getNameOrOID(), oc.getNameOrOID());
-        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
-      }
-    }
-
-    for (AttributeType at : ditContentRule.getRequiredAttributes())
-    {
-      if (at.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_REQUIRED_ATTR.get(
-            ditContentRule.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-      }
-    }
-
-    for (AttributeType at : ditContentRule.getOptionalAttributes())
-    {
-      if (at.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_OPTIONAL_ATTR.get(
-            ditContentRule.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-      }
-    }
-
-    for (AttributeType at : ditContentRule.getProhibitedAttributes())
-    {
-      if (at.isObsolete())
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_PROHIBITED_ATTR.get(
-            ditContentRule.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
-      }
-    }
-
     // If there is no existing rule, then we're adding a new DIT content rule.
     // Otherwise, we're replacing an existing one.
     if (existingDCR == null)
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
index 4cddedd..c7cb419 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
@@ -2162,7 +2162,7 @@
     String nameFormName = "testaddnameformwithobsoleteoc";
     assertFalse(DirectoryServer.getSchema().hasNameForm(nameFormName));
 
-    runModify(argsNotPermissive(), ldif, UNWILLING_TO_PERFORM);
+    runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
     assertFalse(DirectoryServer.getSchema().hasNameForm(nameFormName));
   }
 
@@ -2811,7 +2811,7 @@
               "AUX testAddDITContentRuleObsoleteAuxOCAuxiliary " +
               "X-ORIGIN 'SchemaBackendTestCase' )");
 
-    runModify(argsNotPermissive(), ldif, UNWILLING_TO_PERFORM);
+    runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
   }
 
   /**

--
Gitblit v1.10.0