mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
23.31.2007 0e8ee12a886660ff23c27eb97199ad97ce94df80
opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -30,10 +30,13 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
@@ -44,6 +47,7 @@
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.admin.std.meta.PluginCfgDefn;
import org.opends.server.admin.std.server.PluginCfg;
import org.opends.server.admin.std.server.PluginRootCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.plugin.DirectoryServerPlugin;
@@ -157,6 +161,9 @@
               DirectoryServerPlugin<? extends PluginCfg>>
                    registeredPlugins;
  // The plugin root configuration read at server startup.
  private PluginRootCfg pluginRootConfig;
  // The lock that will provide threadsafe access to the sets of registered
  // plugins.
  private ReentrantLock pluginLock;
@@ -254,17 +261,18 @@
         managementContext.getRootConfiguration();
    // Register as an add and delete listener with the root configuration so we
    // can be notified if any plugin entries are added or removed.
    rootConfiguration.addPluginAddListener(this);
    rootConfiguration.addPluginDeleteListener(this);
    // Get the plugin root configuration and register with it as an add and
    // delete listener so we can be notified if any plugin entries are added or
    // removed.
    pluginRootConfig = rootConfiguration.getPluginRoot();
    pluginRootConfig.addPluginAddListener(this);
    pluginRootConfig.addPluginDeleteListener(this);
    //Initialize the existing plugins.
    for (String pluginName : rootConfiguration.listPlugins())
    for (String pluginName : pluginRootConfig.listPlugins())
    {
      PluginCfg pluginConfiguration =
           rootConfiguration.getPlugin(pluginName);
      PluginCfg pluginConfiguration = pluginRootConfig.getPlugin(pluginName);
      if (! pluginConfiguration.isEnabled())
      {
@@ -528,168 +536,229 @@
        switch (t)
        {
          case STARTUP:
            startupPlugins = addPlugin(startupPlugins, plugin);
            startupPlugins =
                 addPlugin(startupPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderStartup());
            break;
          case SHUTDOWN:
            shutdownPlugins = addPlugin(shutdownPlugins, plugin);
            shutdownPlugins =
                 addPlugin(shutdownPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderShutdown());
            break;
          case POST_CONNECT:
            postConnectPlugins = addPlugin(postConnectPlugins, plugin);
            postConnectPlugins =
                 addPlugin(postConnectPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostConnect());
            break;
          case POST_DISCONNECT:
            postDisconnectPlugins = addPlugin(postDisconnectPlugins, plugin);
            postDisconnectPlugins =
                 addPlugin(postDisconnectPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostDisconnect());
            break;
          case LDIF_IMPORT:
            ldifImportPlugins = addPlugin(ldifImportPlugins, plugin);
            ldifImportPlugins =
                 addPlugin(ldifImportPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderLDIFImport());
            break;
          case LDIF_EXPORT:
            ldifExportPlugins = addPlugin(ldifExportPlugins, plugin);
            ldifExportPlugins =
                 addPlugin(ldifExportPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderLDIFExport());
            break;
          case PRE_PARSE_ABANDON:
            preParseAbandonPlugins = addPlugin(preParseAbandonPlugins, plugin);
            preParseAbandonPlugins =
                 addPlugin(preParseAbandonPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseAbandon());
            break;
          case PRE_PARSE_ADD:
            preParseAddPlugins = addPlugin(preParseAddPlugins, plugin);
            preParseAddPlugins =
                 addPlugin(preParseAddPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseAdd());
            break;
          case PRE_PARSE_BIND:
            preParseBindPlugins = addPlugin(preParseBindPlugins, plugin);
            preParseBindPlugins =
                 addPlugin(preParseBindPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseBind());
            break;
          case PRE_PARSE_COMPARE:
            preParseComparePlugins = addPlugin(preParseComparePlugins, plugin);
            preParseComparePlugins =
                 addPlugin(preParseComparePlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseCompare());
            break;
          case PRE_PARSE_DELETE:
            preParseDeletePlugins = addPlugin(preParseDeletePlugins, plugin);
            preParseDeletePlugins =
                 addPlugin(preParseDeletePlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseDelete());
            break;
          case PRE_PARSE_EXTENDED:
            preParseExtendedPlugins = addPlugin(preParseExtendedPlugins,
                                                plugin);
            preParseExtendedPlugins =
                 addPlugin(preParseExtendedPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseExtended());
            break;
          case PRE_PARSE_MODIFY:
            preParseModifyPlugins = addPlugin(preParseModifyPlugins, plugin);
            preParseModifyPlugins =
                 addPlugin(preParseModifyPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseModify());
            break;
          case PRE_PARSE_MODIFY_DN:
            preParseModifyDNPlugins = addPlugin(preParseModifyDNPlugins,
                                                plugin);
            preParseModifyDNPlugins =
                 addPlugin(preParseModifyDNPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseModifyDN());
            break;
          case PRE_PARSE_SEARCH:
            preParseSearchPlugins = addPlugin(preParseSearchPlugins, plugin);
            preParseSearchPlugins =
                 addPlugin(preParseSearchPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseSearch());
            break;
          case PRE_PARSE_UNBIND:
            preParseUnbindPlugins = addPlugin(preParseUnbindPlugins, plugin);
            preParseUnbindPlugins =
                 addPlugin(preParseUnbindPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreParseUnbind());
            break;
          case PRE_OPERATION_ADD:
            preOperationAddPlugins = addPlugin(preOperationAddPlugins, plugin);
            preOperationAddPlugins =
                 addPlugin(preOperationAddPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreOperationAdd());
            break;
          case PRE_OPERATION_BIND:
            preOperationBindPlugins = addPlugin(preOperationBindPlugins,
                                                plugin);
            preOperationBindPlugins =
                 addPlugin(preOperationBindPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreOperationBind());
            break;
          case PRE_OPERATION_COMPARE:
            preOperationComparePlugins = addPlugin(preOperationComparePlugins,
                                                   plugin);
            preOperationComparePlugins =
                 addPlugin(preOperationComparePlugins,plugin, t,
                      pluginRootConfig.getPluginOrderPreOperationCompare());
            break;
          case PRE_OPERATION_DELETE:
            preOperationDeletePlugins = addPlugin(preOperationDeletePlugins,
                                                  plugin);
            preOperationDeletePlugins =
                 addPlugin(preOperationDeletePlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreOperationDelete());
            break;
          case PRE_OPERATION_EXTENDED:
            preOperationExtendedPlugins = addPlugin(preOperationExtendedPlugins,
                                                    plugin);
            preOperationExtendedPlugins =
                 addPlugin(preOperationExtendedPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPreOperationExtended());
            break;
          case PRE_OPERATION_MODIFY:
            preOperationModifyPlugins = addPlugin(preOperationModifyPlugins,
                                                  plugin);
            preOperationModifyPlugins =
                 addPlugin(preOperationModifyPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreOperationModify());
            break;
          case PRE_OPERATION_MODIFY_DN:
            preOperationModifyDNPlugins = addPlugin(preOperationModifyDNPlugins,
                                                    plugin);
            preOperationModifyDNPlugins =
                 addPlugin(preOperationModifyDNPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPreOperationModifyDN());
            break;
          case PRE_OPERATION_SEARCH:
            preOperationSearchPlugins = addPlugin(preOperationSearchPlugins,
                                                  plugin);
            preOperationSearchPlugins =
                 addPlugin(preOperationSearchPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPreOperationSearch());
            break;
          case POST_OPERATION_ABANDON:
            postOperationAbandonPlugins = addPlugin(postOperationAbandonPlugins,
                                                    plugin);
            postOperationAbandonPlugins =
                 addPlugin(postOperationAbandonPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationAbandon());
            break;
          case POST_OPERATION_ADD:
            postOperationAddPlugins = addPlugin(postOperationAddPlugins,
                                                plugin);
            postOperationAddPlugins =
                 addPlugin(postOperationAddPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostOperationAdd());
            break;
          case POST_OPERATION_BIND:
            postOperationBindPlugins = addPlugin(postOperationBindPlugins,
                                                 plugin);
            postOperationBindPlugins =
                 addPlugin(postOperationBindPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostOperationBind());
            break;
          case POST_OPERATION_COMPARE:
            postOperationComparePlugins = addPlugin(postOperationComparePlugins,
                                                    plugin);
            postOperationComparePlugins =
                 addPlugin(postOperationComparePlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationCompare());
            break;
          case POST_OPERATION_DELETE:
            postOperationDeletePlugins = addPlugin(postOperationDeletePlugins,
                                                   plugin);
            postOperationDeletePlugins =
                 addPlugin(postOperationDeletePlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationDelete());
            break;
          case POST_OPERATION_EXTENDED:
            postOperationExtendedPlugins =
                 addPlugin(postOperationExtendedPlugins, plugin);
                 addPlugin(postOperationExtendedPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationExtended());
            break;
          case POST_OPERATION_MODIFY:
            postOperationModifyPlugins = addPlugin(postOperationModifyPlugins,
                                                   plugin);
            postOperationModifyPlugins =
                 addPlugin(postOperationModifyPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationModify());
            break;
          case POST_OPERATION_MODIFY_DN:
            postOperationModifyDNPlugins =
                 addPlugin(postOperationModifyDNPlugins, plugin);
                 addPlugin(postOperationModifyDNPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationModifyDN());
            break;
          case POST_OPERATION_SEARCH:
            postOperationSearchPlugins = addPlugin(postOperationSearchPlugins,
                                                   plugin);
            postOperationSearchPlugins =
                 addPlugin(postOperationSearchPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationSearch());
            break;
          case POST_OPERATION_UNBIND:
            postOperationUnbindPlugins = addPlugin(postOperationUnbindPlugins,
                                                   plugin);
            postOperationUnbindPlugins =
                 addPlugin(postOperationUnbindPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostOperationUnbind());
            break;
          case POST_RESPONSE_ADD:
            postResponseAddPlugins = addPlugin(postResponseAddPlugins, plugin);
            postResponseAddPlugins =
                 addPlugin(postResponseAddPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostResponseAdd());
            break;
          case POST_RESPONSE_BIND:
            postResponseBindPlugins = addPlugin(postResponseBindPlugins,
                                                plugin);
            postResponseBindPlugins =
                 addPlugin(postResponseBindPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostResponseBind());
            break;
          case POST_RESPONSE_COMPARE:
            postResponseComparePlugins = addPlugin(postResponseComparePlugins,
                                                   plugin);
            postResponseComparePlugins =
                 addPlugin(postResponseComparePlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostResponseCompare());
            break;
          case POST_RESPONSE_DELETE:
            postResponseDeletePlugins = addPlugin(postResponseDeletePlugins,
                                                  plugin);
            postResponseDeletePlugins =
                 addPlugin(postResponseDeletePlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostResponseDelete());
            break;
          case POST_RESPONSE_EXTENDED:
            postResponseExtendedPlugins = addPlugin(postResponseExtendedPlugins,
                                                    plugin);
            postResponseExtendedPlugins =
                 addPlugin(postResponseExtendedPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostResponseExtended());
            break;
          case POST_RESPONSE_MODIFY:
            postResponseModifyPlugins = addPlugin(postResponseModifyPlugins,
                                                  plugin);
            postResponseModifyPlugins =
                 addPlugin(postResponseModifyPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostResponseModify());
            break;
          case POST_RESPONSE_MODIFY_DN:
            postResponseModifyDNPlugins = addPlugin(postResponseModifyDNPlugins,
                                                    plugin);
            postResponseModifyDNPlugins =
                 addPlugin(postResponseModifyDNPlugins, plugin, t,
                      pluginRootConfig.getPluginOrderPostResponseModifyDN());
            break;
          case POST_RESPONSE_SEARCH:
            postResponseSearchPlugins = addPlugin(postResponseSearchPlugins,
                                                  plugin);
            postResponseSearchPlugins =
                 addPlugin(postResponseSearchPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderPostResponseSearch());
            break;
          case SEARCH_RESULT_ENTRY:
            searchResultEntryPlugins = addPlugin(searchResultEntryPlugins,
                                                 plugin);
            searchResultEntryPlugins =
                 addPlugin(searchResultEntryPlugins, plugin, t,
                           pluginRootConfig.getPluginOrderSearchResultEntry());
            break;
          case SEARCH_RESULT_REFERENCE:
            searchResultReferencePlugins =
                 addPlugin(searchResultReferencePlugins, plugin);
                 addPlugin(searchResultReferencePlugins, plugin, t,
                      pluginRootConfig.getPluginOrderSearchResultReference());
            break;
          case INTERMEDIATE_RESPONSE:
            intermediateResponsePlugins = addPlugin(intermediateResponsePlugins,
                                                    plugin);
            intermediateResponsePlugins =
                 addPlugin(intermediateResponsePlugins, plugin, t,
                      pluginRootConfig.getPluginOrderIntermediateResponse());
            break;
          default:
        }
@@ -708,21 +777,216 @@
   * itself be modified, but rather a new array will be created with one
   * additional element.  The provided plugin will be the last element in the
   * new array.
   * <BR><BR>
   * Note that the only use of this method outside of this class should be for
   * testing purposes.
   *
   * @param  pluginArray  The array containing the existing set of plugins.
   * @param  plugin       The plugin to be added to the array.
   * @param  pluginType   The plugin type for the plugin being registered.
   * @param  pluginOrder  A string that represents the order in which plugins of
   *                      this type should be invoked, or {@code null} if the
   *                      order is not considered important.
   *
   * @return  The new array containing the new set of plugins.
   */
  private DirectoryServerPlugin[] addPlugin(DirectoryServerPlugin[] pluginArray,
                                            DirectoryServerPlugin plugin)
  static DirectoryServerPlugin[] addPlugin(DirectoryServerPlugin[] pluginArray,
                                           DirectoryServerPlugin plugin,
                                           PluginType pluginType,
                                           String pluginOrder)
  {
    DirectoryServerPlugin[] newPlugins =
         new DirectoryServerPlugin[pluginArray.length+1];
    System.arraycopy(pluginArray, 0, newPlugins, 0, pluginArray.length);
    newPlugins[pluginArray.length] = plugin;
    // If the provided plugin order string is null, empty, or contains only a
    // wildcard, then simply add the new plugin to the end of the list.
    // Otherwise, parse the order string and figure out where to put the
    // provided plugin.
    if ((pluginOrder == null) ||
        ((pluginOrder = pluginOrder.trim()).length() == 0) ||
        pluginOrder.equals("*"))
    {
      DirectoryServerPlugin[] newPlugins =
           new DirectoryServerPlugin[pluginArray.length+1];
      System.arraycopy(pluginArray, 0, newPlugins, 0, pluginArray.length);
      newPlugins[pluginArray.length] = plugin;
    return newPlugins;
      return newPlugins;
    }
    else
    {
      // Parse the plugin order into initial and final plugin names.
      boolean starFound = false;
      LinkedHashSet<String> initialPluginNames = new LinkedHashSet<String>();
      LinkedHashSet<String> finalPluginNames   = new LinkedHashSet<String>();
      StringTokenizer tokenizer = new StringTokenizer(pluginOrder, ",");
      while (tokenizer.hasMoreTokens())
      {
        String token = tokenizer.nextToken().trim();
        if (token.length() == 0)
        {
          // Only log the warning once per plugin type.  The plugin array will
          // be empty the first time through, so we can use that to make the
          // determination.
          if (pluginArray.length == 0)
          {
            int    msgID   = MSGID_CONFIG_PLUGIN_EMPTY_ELEMENT_IN_ORDER;
            String message = getMessage(msgID, pluginType.getName());
            logError(ErrorLogCategory.CONFIGURATION,
                     ErrorLogSeverity.SEVERE_WARNING, message, msgID);
          }
        }
        else if (token.equals("*"))
        {
          if (starFound)
          {
            // Only log the warning once per plugin type.  The plugin array will
            // be empty the first time through, so we can use that to make the
            // determination.
            if (pluginArray.length == 0)
            {
              int    msgID   = MSGID_CONFIG_PLUGIN_MULTIPLE_WILDCARDS_IN_ORDER;
              String message = getMessage(msgID, pluginType.getName());
              logError(ErrorLogCategory.CONFIGURATION,
                       ErrorLogSeverity.SEVERE_WARNING, message, msgID);
            }
          }
          else
          {
            starFound = true;
          }
        }
        else
        {
          String lowerName = toLowerCase(token);
          if (starFound)
          {
            if (initialPluginNames.contains(lowerName) ||
                finalPluginNames.contains(lowerName))
            {
              // Only log the warning once per plugin type.  The plugin array
              // will be empty the first time through, so we can use that to
              // make the determination.
              if (pluginArray.length == 0)
              {
                int    msgID   = MSGID_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES;
                String message = getMessage(msgID, pluginType.getName(), token);
                logError(ErrorLogCategory.CONFIGURATION,
                         ErrorLogSeverity.SEVERE_WARNING, message, msgID);
              }
            }
            finalPluginNames.add(lowerName);
          }
          else
          {
            if (initialPluginNames.contains(lowerName))
            {
              // Only log the warning once per plugin type.  The plugin array
              // will be empty the first time through, so we can use that to
              // make the determination.
              if (pluginArray.length == 0)
              {
                int    msgID   = MSGID_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES;
                String message = getMessage(msgID, pluginType.getName(), token);
                logError(ErrorLogCategory.CONFIGURATION,
                         ErrorLogSeverity.SEVERE_WARNING, message, msgID);
              }
            }
            initialPluginNames.add(lowerName);
          }
        }
      }
      if (! starFound)
      {
        // Only log the warning once per plugin type.  The plugin array will be
        // empty the first time through, so we can use that to make the
        // determination.
        if (pluginArray.length == 0)
        {
          int    msgID   = MSGID_CONFIG_PLUGIN_ORDER_NO_WILDCARD;
          String message = getMessage(msgID, pluginType.getName());
          logError(ErrorLogCategory.CONFIGURATION,
                   ErrorLogSeverity.SEVERE_WARNING, message, msgID);
        }
      }
      // Parse the array of already registered plugins to sort them accordingly.
      HashMap<String,DirectoryServerPlugin> initialPlugins =
           new HashMap<String,DirectoryServerPlugin>(initialPluginNames.size());
      HashMap<String,DirectoryServerPlugin> finalPlugins =
           new HashMap<String,DirectoryServerPlugin>(finalPluginNames.size());
      ArrayList<DirectoryServerPlugin> otherPlugins =
           new ArrayList<DirectoryServerPlugin>();
      for (DirectoryServerPlugin p : pluginArray)
      {
        DN dn = p.getPluginEntryDN();
        String lowerName =
             toLowerCase(dn.getRDN().getAttributeValue(0).getStringValue());
        if (initialPluginNames.contains(lowerName))
        {
          initialPlugins.put(lowerName, p);
        }
        else if (finalPluginNames.contains(lowerName))
        {
          finalPlugins.put(lowerName, p);
        }
        else
        {
          otherPlugins.add(p);
        }
      }
      // Get the name of the provided plugin from its RDN value and put it in
      // the correct category.
      DN dn = plugin.getPluginEntryDN();
      String lowerName =
           toLowerCase(dn.getRDN().getAttributeValue(0).getStringValue());
      if (initialPluginNames.contains(lowerName))
      {
        initialPlugins.put(lowerName, plugin);
      }
      else if (finalPluginNames.contains(lowerName))
      {
        finalPlugins.put(lowerName, plugin);
      }
      else
      {
        otherPlugins.add(plugin);
      }
      // Compile a list of all the plugins in the correct order, convert it to
      // an array, and return it.
      ArrayList<DirectoryServerPlugin> newList =
           new ArrayList<DirectoryServerPlugin>(pluginArray.length+1);
      for (String name : initialPluginNames)
      {
        DirectoryServerPlugin p = initialPlugins.get(name);
        if (p != null)
        {
          newList.add(p);
        }
      }
      newList.addAll(otherPlugins);
      for (String name : finalPluginNames)
      {
        DirectoryServerPlugin p = finalPlugins.get(name);
        if (p != null)
        {
          newList.add(p);
        }
      }
      DirectoryServerPlugin[] newPlugins =
           new DirectoryServerPlugin[newList.size()];
      newList.toArray(newPlugins);
      return newPlugins;
    }
  }