From 6bed45cbfe8dba8557a6b8027b6b8fd9992a4e51 Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Thu, 20 Dec 2007 02:33:30 +0000
Subject: [PATCH] Issue 2741. Adding and removing ACI makes OpenDS unstable. Comments in issue.

---
 opends/src/server/org/opends/server/core/AccessControlConfigManager.java |  182 ++++++++++++++++++++++++---------------------
 1 files changed, 97 insertions(+), 85 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/AccessControlConfigManager.java b/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
index ad4b8da..950e702 100644
--- a/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
+++ b/opends/src/server/org/opends/server/core/AccessControlConfigManager.java
@@ -184,6 +184,9 @@
     // order to handle configuration changes.
     accessControlConfiguration.addChangeListener(this);
 
+    //This makes TestCaseUtils.reStartServer happy.
+    currentConfiguration=null;
+
     // The configuration looks valid, so install it.
     updateConfiguration(accessControlConfiguration);
   }
@@ -201,16 +204,17 @@
    * @throws  InitializationException  If the access control handler provider
    *                                   could not be instantiated.
    */
+
   private void updateConfiguration(AccessControlHandlerCfg newConfiguration)
           throws ConfigException, InitializationException
   {
-    DN configEntryDN = newConfiguration.dn();
     String newHandlerClass = null;
+    boolean enabledOld = false, enabledNew = newConfiguration.isEnabled();
 
     if (currentConfiguration == null)
     {
       // Initialization phase.
-      if (newConfiguration.isEnabled())
+      if (enabledNew)
       {
         newHandlerClass = newConfiguration.getJavaClass();
       }
@@ -218,97 +222,103 @@
       {
         newHandlerClass = DefaultAccessControlHandler.class.getName();
       }
-    }
-    else
-    {
-      boolean enabledOld = currentConfiguration.isEnabled();
-      boolean enabledNew = newConfiguration.isEnabled();
-
-      if ((! enabledOld) && enabledNew)
-      {
-        // Access control has been enabled - get the new class name.
+      //Get a new handler, initialize it and make it the current handler.
+      accessControlHandler.getAndSet(getHandler(newHandlerClass,
+              newConfiguration, true, false));
+    } else {
+      enabledOld = currentConfiguration.isEnabled();
+      if(enabledNew) {
+        //Access control is either being enabled or a attribute in the
+        //configuration has changed such as class name or a global ACI.
         newHandlerClass = newConfiguration.getJavaClass();
-      }
-      else if (enabledOld && (! enabledNew))
-      {
-        // Access control has been disabled - get the default handler class
-        // name.
+        String oldHandlerClass = currentConfiguration.getJavaClass();
+        //Check if moving from not enabled to enabled state.
+        if(!enabledOld) {
+           AccessControlHandler oldHandler =
+                   accessControlHandler.getAndSet(getHandler(newHandlerClass,
+                                                  newConfiguration, true, true));
+           oldHandler.finalizeAccessControlHandler();
+        } else {
+          //Check if the class name is being changed.
+          if(!newHandlerClass.equals(oldHandlerClass)) {
+           AccessControlHandler oldHandler =
+            accessControlHandler.getAndSet(getHandler(newHandlerClass,
+                    newConfiguration, true, true));
+            oldHandler.finalizeAccessControlHandler();
+          } else {
+            //Some other attribute has changed, try to get a new non-initialized
+            //handler, but keep the old handler.
+            getHandler(newHandlerClass,newConfiguration, false, false);
+          }
+        }
+      } else if (enabledOld && (! enabledNew)) {
+        //Access control has been disabled, switch to the default handler and
+        //finalize the old handler.
         newHandlerClass = DefaultAccessControlHandler.class.getName();
-      }
-      else if (enabledNew)
-      {
-        // Access control is already enabled, but still get the handler class
-        // name to see if it has changed.
-        newHandlerClass = newConfiguration.getJavaClass();
-      }
-    }
-
-    // If the access control handler provider class has changed, finalize the
-    // old one and instantiate the new one.
-    if (newHandlerClass != null)
-    {
-      AccessControlHandler<? extends AccessControlHandlerCfg> newHandler;
-      try
-      {
-        if (newConfiguration.isEnabled())
-        {
-          newHandler = loadHandler(newHandlerClass, newConfiguration, true);
-        }
-        else
-        {
-          newHandler = new DefaultAccessControlHandler();
-          newHandler.initializeAccessControlHandler(null);
-        }
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        Message message = ERR_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER.
-            get(newHandlerClass, String.valueOf(configEntryDN.toString()),
-                stackTraceToSingleLineString(e));
-        throw new InitializationException(message, e);
-      }
-
-      // Switch the handlers without interfering with other threads.
-      AccessControlHandler oldHandler =
-           accessControlHandler.getAndSet(newHandler);
-
-      if (oldHandler != null)
-      {
+        AccessControlHandler oldHandler =
+                accessControlHandler.getAndSet(getHandler(newHandlerClass,
+                        newConfiguration, false, true));
         oldHandler.finalizeAccessControlHandler();
       }
-
-      // If access control has been disabled put a warning in the log.
-      if (newHandlerClass.equals(DefaultAccessControlHandler.class.getName()))
-      {
-        Message message = WARN_CONFIG_AUTHZ_DISABLED.get();
-        logError(message);
-        if (currentConfiguration != null)
-        {
-          DirectoryServer.sendAlertNotification(this,
-               ALERT_TYPE_ACCESS_CONTROL_DISABLED, message);
-        }
-      }
-      else
-      {
-        Message message = NOTE_CONFIG_AUTHZ_ENABLED.get(newHandlerClass);
-        logError(message);
-        if (currentConfiguration != null)
-        {
-          DirectoryServer.sendAlertNotification(this,
-               ALERT_TYPE_ACCESS_CONTROL_ENABLED, message);
-        }
-      }
     }
-
     // Switch in the local configuration.
     currentConfiguration = newConfiguration;
   }
 
+  /**
+   * Instantiates a new Access Control Handler using the specified class name,
+   * configuration.
+   *
+   * @param handlerClassName The name of the handler to instantiate.
+   * @param config The configuration to use when instantiating a new handler.
+   * @param initHandler <code>True</code> if the new handler should be
+   *                    initialized.
+   * @param logMessage <code>True</code> if an error message should be logged
+   *                                     and an alert should be sent.
+   * @return The newly instantiated handler.
+   *
+   * @throws InitializationException  If an error occurs instantiating the
+   *                                  the new handler.
+   */
+  AccessControlHandler<? extends AccessControlHandlerCfg>
+  getHandler(String handlerClassName, AccessControlHandlerCfg config,
+             boolean initHandler, boolean logMessage)
+          throws InitializationException {
+    AccessControlHandler<? extends AccessControlHandlerCfg> newHandler;
+    try {
+      if(handlerClassName.equals(DefaultAccessControlHandler.class.getName())) {
+        newHandler = new DefaultAccessControlHandler();
+        newHandler.initializeAccessControlHandler(null);
+        if(logMessage) {
+          Message message = WARN_CONFIG_AUTHZ_DISABLED.get();
+          logError(message);
+          if (currentConfiguration != null) {
+            DirectoryServer.sendAlertNotification(this,
+                    ALERT_TYPE_ACCESS_CONTROL_DISABLED, message);
+          }
+        }
+      } else {
+        newHandler = loadHandler(handlerClassName, config, initHandler);
+        if(logMessage) {
+          Message message = NOTE_CONFIG_AUTHZ_ENABLED.get(handlerClassName);
+          logError(message);
+          if (currentConfiguration != null) {
+            DirectoryServer.sendAlertNotification(this,
+                    ALERT_TYPE_ACCESS_CONTROL_ENABLED, message);
+          }
+        }
+      }
+    } catch (Exception e) {
+      if (debugEnabled()) {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+      Message message = ERR_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER.
+              get(handlerClassName, String.valueOf(config.dn().toString()),
+                      stackTraceToSingleLineString(e));
+      throw new InitializationException(message, e);
+    }
+    return newHandler;
+  }
 
 
   /**
@@ -446,7 +456,9 @@
         Method method =
           provider.getClass().getMethod("initializeAccessControlHandler",
                   configuration.definition().getServerConfigurationClass());
-        method.invoke(provider, configuration);
+        if(initialize) {
+          method.invoke(provider, configuration);
+        }
       }
       else
       {

--
Gitblit v1.10.0