From 3295ecee421bbfab950bf5e4bb32e9cc95746f5e Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 30 Sep 2026 12:25:59 +0000
Subject: [PATCH] [#1118] Register the shipped Referential Integrity plugin for the pre-operation types check-references needs, and refuse check-references without them (#1123)

---
 opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
index 1b2a5bc..f42d845 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -33,6 +33,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -105,6 +106,9 @@
 {
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
+  /** The plugin types {@code check-references} needs: the references are checked in these hooks. */
+  private static final Set<PluginCfgDefn.PluginType> CHECK_REFERENCES_PLUGIN_TYPES = Collections.unmodifiableSet(
+      EnumSet.of(PluginCfgDefn.PluginType.PREOPERATIONADD, PluginCfgDefn.PluginType.PREOPERATIONMODIFY));
 
 
   /** Current plugin configuration. */
@@ -169,11 +173,19 @@
     pluginCfg.addReferentialIntegrityChangeListener(this);
     LinkedList<LocalizableMessage> unacceptableReasons = new LinkedList<>();
 
-    if (!isConfigurationAcceptable(pluginCfg, unacceptableReasons))
+    if (!isConfigurationAcceptableIgnoringCheckReferencesPluginTypes(pluginCfg, unacceptableReasons))
     {
       throw new ConfigException(unacceptableReasons.getFirst());
     }
 
+    // Enabling the plugin or changing its configuration is refused without these types, but a configuration
+    // already stored without them (the entry shipped before issue #1118) is loaded with a warning: refusing
+    // it would also stop the delete and modify DN clean-up, which does not need them.
+    for (PluginCfgDefn.PluginType t : getMissingCheckReferencesPluginTypes(pluginCfg))
+    {
+      logger.warn(WARN_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPE.get(pluginCfg.dn(), t, t));
+    }
+
     applyConfigurationChange(pluginCfg);
 
     // Set up log file. Note: it is not allowed to change once the plugin is active.
@@ -255,9 +267,39 @@
   public boolean isConfigurationAcceptable(PluginCfg configuration,
                                            List<LocalizableMessage> unacceptableReasons)
   {
-    boolean isAcceptable = true;
     ReferentialIntegrityPluginCfg pluginCfg =
          (ReferentialIntegrityPluginCfg) configuration;
+    boolean isAcceptable = isConfigurationAcceptableIgnoringCheckReferencesPluginTypes(pluginCfg, unacceptableReasons);
+
+    for (PluginCfgDefn.PluginType t : getMissingCheckReferencesPluginTypes(pluginCfg))
+    {
+      isAcceptable = false;
+      unacceptableReasons.add(ERR_PLUGIN_REFERENT_CHECK_REFERENCES_WITHOUT_PLUGIN_TYPE.get(t, t));
+    }
+    return isAcceptable;
+  }
+
+  /**
+   * Returns the plugin types {@code check-references} needs that the configuration does not list. The references
+   * are checked in the pre-operation add and modify hooks, which the plugin manager only calls for the plugin types
+   * listed in the configuration.
+   */
+  private static Set<PluginCfgDefn.PluginType> getMissingCheckReferencesPluginTypes(
+      ReferentialIntegrityPluginCfg pluginCfg)
+  {
+    if (!pluginCfg.isCheckReferences())
+    {
+      return Collections.emptySet();
+    }
+    Set<PluginCfgDefn.PluginType> missing = EnumSet.copyOf(CHECK_REFERENCES_PLUGIN_TYPES);
+    missing.removeAll(pluginCfg.getPluginType());
+    return missing;
+  }
+
+  private boolean isConfigurationAcceptableIgnoringCheckReferencesPluginTypes(
+      ReferentialIntegrityPluginCfg pluginCfg, List<LocalizableMessage> unacceptableReasons)
+  {
+    boolean isAcceptable = true;
 
     for (PluginCfgDefn.PluginType t : pluginCfg.getPluginType())
     {

--
Gitblit v1.10.0