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

neil_a_wilson
23.31.2007 0e8ee12a886660ff23c27eb97199ad97ce94df80
Provide a way to control the order in which plugins are invoked.  This
implementation is similar to that used by DSEE 6. The "cn=Plugins,cn=config"
configuration entry now supports a number of new configuration attributes
(one per plugin type) that can be used to control the invocation order for
plugins of that type. The plugin order specification should be a string that
is a comma-delimited list of the names of the plugins in the order in which
they should be invoked, and it should also include an asterisk to indicate
the order in which any unmatched plugins should be invoked.

For example:

ds-cfg-plugin-order-pre-operation-add: Entry UUID, *

This indicates that the "Entry UUID" plugin should be invoked before any other
pre-operation add plugins.

The plugin order is evaluated only at startup, and any problems or
inconsistencies detected (e.g., the same plugin name listed twice in the order,
or a plugin order that does not contain a wildcard character) will generate
warning messages in the server's error log.

OpenDS Issue Number: 253
2 files added
5 files modified
2703 ■■■■■ changed files
opends/resource/config/config.ldif 1 ●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 216 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PluginRootConfiguration.xml 1322 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/PluginConfigManager.java 434 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ConfigMessages.java 61 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/PluginConfigManagerTestCase.java 659 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1245,6 +1245,7 @@
dn: cn=Plugins,cn=config
objectClass: top
objectClass: ds-cfg-branch
objectClass: ds-cfg-plugin-root
cn: Plugins
dn: cn=Entry UUID,cn=Plugins,cn=config
opends/resource/schema/02-config.ldif
@@ -1283,6 +1283,180 @@
  NAME 'ds-cfg-index-substring-length'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.384 NAME 'ds-cfg-plugin-order-startup'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.385 NAME 'ds-cfg-plugin-order-shutdown'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.386
  NAME 'ds-cfg-plugin-order-post-connect' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.387
  NAME 'ds-cfg-plugin-order-post-disconnect'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.388
  NAME 'ds-cfg-plugin-order-ldif-import' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.389
  NAME 'ds-cfg-plugin-order-ldif-export' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.390
  NAME 'ds-cfg-plugin-order-pre-parse-abandon'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.391
  NAME 'ds-cfg-plugin-order-pre-parse-add' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.392
  NAME 'ds-cfg-plugin-order-pre-parse-bind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.393
  NAME 'ds-cfg-plugin-order-pre-parse-compare'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.394
  NAME 'ds-cfg-plugin-order-pre-parse-delete'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.395
  NAME 'ds-cfg-plugin-order-pre-parse-extended'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.396
  NAME 'ds-cfg-plugin-order-pre-parse-modify'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.397
  NAME 'ds-cfg-plugin-order-pre-parse-modify-dn'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.398
  NAME 'ds-cfg-plugin-order-pre-parse-search'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.399
  NAME 'ds-cfg-plugin-order-pre-parse-unbind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.400
  NAME 'ds-cfg-plugin-order-pre-operation-add'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.401
  NAME 'ds-cfg-plugin-order-pre-operation-bind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.402
  NAME 'ds-cfg-plugin-order-pre-operation-compare'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.403
  NAME 'ds-cfg-plugin-order-pre-operation-delete'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.404
  NAME 'ds-cfg-plugin-order-pre-operation-extended'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.405
  NAME 'ds-cfg-plugin-order-pre-operation-modify'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.406
  NAME 'ds-cfg-plugin-order-pre-operation-modify-dn'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.407
  NAME 'ds-cfg-plugin-order-pre-operation-search'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.408
  NAME 'ds-cfg-plugin-order-post-operation-abandon'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.409
  NAME 'ds-cfg-plugin-order-post-operation-add'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.410
  NAME 'ds-cfg-plugin-order-post-operation-bind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.411
  NAME 'ds-cfg-plugin-order-post-operation-compare'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.412
  NAME 'ds-cfg-plugin-order-post-operation-delete'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.413
  NAME 'ds-cfg-plugin-order-post-operation-extended'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.414
  NAME 'ds-cfg-plugin-order-post-operation-modify'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.415
  NAME 'ds-cfg-plugin-order-post-operation-modify-dn'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.416
  NAME 'ds-cfg-plugin-order-post-operation-search'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.417
  NAME 'ds-cfg-plugin-order-post-operation-unbind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.418
  NAME 'ds-cfg-plugin-order-post-response-add'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.419
  NAME 'ds-cfg-plugin-order-post-response-bind'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.420
  NAME 'ds-cfg-plugin-order-post-response-compare'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.421
  NAME 'ds-cfg-plugin-order-post-response-delete'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.422
  NAME 'ds-cfg-plugin-order-post-response-extended'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.423
  NAME 'ds-cfg-plugin-order-post-response-modify'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.424
  NAME 'ds-cfg-plugin-order-post-response-modify-dn'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.425
  NAME 'ds-cfg-plugin-order-post-response-search'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.426
  NAME 'ds-cfg-plugin-order-search-result-entry'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.427
  NAME 'ds-cfg-plugin-order-search-result-reference'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.428
  NAME 'ds-cfg-plugin-order-intermediate-response'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1832,4 +2006,46 @@
  ds-cfg-include-filter $ ds-cfg-cache-directory $ ds-cfg-cache-type $
  ds-cfg-persistent-cache $ ds-cfg-database-cache-percent $
  ds-cfg-database-cache-size ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.114 NAME 'ds-cfg-plugin-root'
  SUP top AUXILIARY MAY ( ds-cfg-plugin-order-startup $
  ds-cfg-plugin-order-shutdown $ ds-cfg-plugin-order-post-connect $
  ds-cfg-plugin-order-post-disconnect $ ds-cfg-plugin-order-ldif-import $
  ds-cfg-plugin-order-ldif-export $ ds-cfg-plugin-order-pre-parse-abandon $
  ds-cfg-plugin-order-pre-parse-add $ ds-cfg-plugin-order-pre-parse-bind $
  ds-cfg-plugin-order-pre-parse-compare $
  ds-cfg-plugin-order-pre-parse-delete $
  ds-cfg-plugin-order-pre-parse-extended $
  ds-cfg-plugin-order-pre-parse-modify $
  ds-cfg-plugin-order-pre-parse-modify-dn $
  ds-cfg-plugin-order-pre-parse-search $ ds-cfg-plugin-order-pre-parse-unbind $
  ds-cfg-plugin-order-pre-operation-add $
  ds-cfg-plugin-order-pre-operation-bind $
  ds-cfg-plugin-order-pre-operation-compare $
  ds-cfg-plugin-order-pre-operation-delete $
  ds-cfg-plugin-order-pre-operation-extended $
  ds-cfg-plugin-order-pre-operation-modify $
  ds-cfg-plugin-order-pre-operation-modify-dn $
  ds-cfg-plugin-order-pre-operation-search $
  ds-cfg-plugin-order-post-operation-abandon $
  ds-cfg-plugin-order-post-operation-add $
  ds-cfg-plugin-order-post-operation-bind $
  ds-cfg-plugin-order-post-operation-compare $
  ds-cfg-plugin-order-post-operation-delete $
  ds-cfg-plugin-order-post-operation-extended $
  ds-cfg-plugin-order-post-operation-modify $
  ds-cfg-plugin-order-post-operation-modify-dn $
  ds-cfg-plugin-order-post-operation-search $
  ds-cfg-plugin-order-post-operation-unbind $
  ds-cfg-plugin-order-post-response-add $
  ds-cfg-plugin-order-post-response-bind $
  ds-cfg-plugin-order-post-response-compare $
  ds-cfg-plugin-order-post-response-delete $
  ds-cfg-plugin-order-post-response-extended $
  ds-cfg-plugin-order-post-response-modify $
  ds-cfg-plugin-order-post-response-modify-dn $
  ds-cfg-plugin-order-post-response-search $
  ds-cfg-plugin-order-search-result-entry $
  ds-cfg-plugin-order-search-result-reference $
  ds-cfg-plugin-order-intermediate-response )
  X-ORIGIN 'OpenDS Directory Server' )
opends/src/admin/defn/org/opends/server/admin/std/PluginRootConfiguration.xml
New file
@@ -0,0 +1,1322 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
! CDDL HEADER START
!
! The contents of this file are subject to the terms of the
! Common Development and Distribution License, Version 1.0 only
! (the "License").  You may not use this file except in compliance
! with the License.
!
! You can obtain a copy of the license at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE
! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
! See the License for the specific language governing permissions
! and limitations under the License.
!
! When distributing Covered Code, include this CDDL HEADER in each
! file and include the License file at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
! add the following below this CDDL HEADER, with the fields enclosed
! by brackets "[]" replaced with your own identifying information:
!      Portions Copyright [yyyy] [name of copyright owner]
!
! CDDL HEADER END
!
!
!      Portions Copyright 2007 Sun Microsystems, Inc.
! -->
<adm:managed-object name="plugin-root"
plural-name="plugin-roots"
package="org.opends.server.admin.std" abstract="false"
xmlns:adm="http://www.opends.org/admin"
xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    defines the parent entry for all plugins defined in the server.  It may also
    include configuration attributes that define the order in which those
    plugins should be loaded and invoked.
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.114</ldap:oid>
      <ldap:name>ds-cfg-plugin-root</ldap:name>
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:relation name="plugin">
    <adm:one-to-many />
    <adm:profile name="ldap">
      <ldap:rdn-sequence />
      <ldap:naming-attribute>
        cn
      </ldap:naming-attribute>
    </adm:profile>
  </adm:relation>
  <adm:property name="plugin-order-startup" mandatory="false">
    <adm:synopsis>
      Specifies the order in which startup plugins should be loaded and invoked.
      The value should be a comma-delimited list of plugin names (where the
      plugin name is the RDN value from the plugin configuration entry DN).
      The list may include at most one asterisk to indicate the position of any
      unnamed plugin (and the relative order of those unnamed plugins will be
      undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which startup plugins are loaded and invoked will be
          undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.384</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-startup</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-shutdown" mandatory="false">
    <adm:synopsis>
      Specifies the order in which shutdown plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which shutdown plugins are loaded and invoked will be
          undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.385</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-shutdown</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-connect" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-connect plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-connect plugins are loaded and invoked will be
          undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.386</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-connect</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-disconnect" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-disconnect plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-disconnect plugins are loaded and invoked will
          be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.387</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-disconnect</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-ldif-import" mandatory="false">
    <adm:synopsis>
      Specifies the order in which LDIF import plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which LDIF import plugins are loaded and invoked will be
          undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.388</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-ldif-import</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-ldif-export" mandatory="false">
    <adm:synopsis>
      Specifies the order in which LDIF export plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which LDIF export plugins are loaded and invoked will be
          undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.389</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-ldif-export</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-abandon" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse abandon plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse abandon plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.390</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-abandon</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-add" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse add plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse add plugins are loaded and invoked will
          be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.391</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-add</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-bind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse bind plugins should be loaded and
      invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse bind plugins are loaded and invoked will
          be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.392</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-bind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-compare" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse compare plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse compare plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.393</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-compare</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-delete" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse delete plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse delete plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.394</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-delete</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-extended" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse extended operation plugins should
      be loaded and invoked.  The value should be a comma-delimited list of
      plugin names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse extended operation plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.395</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-extended</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-modify" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse modify plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse modify plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.396</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-modify</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-modify-dn" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse modify DN plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse modify DN plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.397</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-modify-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-search" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse search plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse search plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.398</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-search</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-parse-unbind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-parse unbind plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-parse unbind plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.399</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-parse-unbind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-add" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation add plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation add plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.400</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-add</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-bind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation bind plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation bind plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.401</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-bind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-compare" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation compare plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation compare plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.402</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-compare</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-delete" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation delete plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation delete plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.403</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-delete</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-extended" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation extended operation plugins
      should be loaded and invoked.  The value should be a comma-delimited list
      of plugin names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation extended operation plugins are loaded
          and invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.404</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-extended</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-modify" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation modify plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation modify plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.405</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-modify</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-modify-dn" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation modify DN plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation modify DN plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.406</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-modify-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-pre-operation-search" mandatory="false">
    <adm:synopsis>
      Specifies the order in which pre-operation search plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which pre-operation searc plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.407</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-pre-operation-search</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-abandon" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation abandon plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation abandon plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.408</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-abandon</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-add" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation add plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation add plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.409</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-add</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-bind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation bind plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation bind plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.410</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-bind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-compare" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation compare plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation compare plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.411</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-compare</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-delete" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation delete plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation delete plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.412</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-delete</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-extended" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation extended operation plugins
      should be loaded and invoked.  The value should be a comma-delimited list
      of plugin names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation extended operation plugins are
          loaded and invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.413</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-extended</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-modify" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation modify plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation modify plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.414</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-modify</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-modify-dn" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation modify DN plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation modify DN plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.415</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-modify-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-search" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation search plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation search plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.416</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-search</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-operation-unbind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-operation unbind plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-operation unbind plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.417</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-unbind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-add" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response add plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response add plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.418</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-add</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-bind" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response bind plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response bind plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.419</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-bind</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-compare" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response compare plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response compare plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.420</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-compare</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-delete" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response delete plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response delete plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.421</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-delete</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-extended" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response extended operation plugins
      should be loaded and invoked.  The value should be a comma-delimited list
      of plugin names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response extended operation plugins are loaded
          and invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.422</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-extended</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-modify" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response modify plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response modify plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.423</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-modify</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-modify-dn" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response modify DN plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response modify DN plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.424</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-modify-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-post-response-search" mandatory="false">
    <adm:synopsis>
      Specifies the order in which post-response search plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which post-response search plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.425</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-post-operation-search</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-search-result-entry" mandatory="false">
    <adm:synopsis>
      Specifies the order in which search result entry plugins should be loaded
      and invoked.  The value should be a comma-delimited list of plugin names
      (where the plugin name is the RDN value from the plugin configuration
      entry DN).  The list may include at most one asterisk to indicate the
      position of any unnamed plugin (and the relative order of those unnamed
      plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which search result entry plugins are loaded and invoked
          will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.426</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-search-result-entry</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-search-result-reference" mandatory="false">
    <adm:synopsis>
      Specifies the order in which search result reference plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which search result reference plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.427</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-search-result-reference</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="plugin-order-intermediate-response" mandatory="false">
    <adm:synopsis>
      Specifies the order in which intermediate response plugins should be
      loaded and invoked.  The value should be a comma-delimited list of plugin
      names (where the plugin name is the RDN value from the plugin
      configuration entry DN).  The list may include at most one asterisk to
      indicate the position of any unnamed plugin (and the relative order of
      those unnamed plugins will be undefined).
    </adm:synopsis>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          The order in which intermediate response plugins are loaded and
          invoked will be undefined.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.428</ldap:oid>
        <ldap:name>ds-cfg-plugin-order-intermediate-response</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -146,17 +146,11 @@
      </cli:relation>
    </adm:profile>
  </adm:relation>
  <adm:relation name="plugin">
    <adm:one-to-many />
  <adm:relation name="plugin-root" managed-object-name="plugin-root">
    <adm:one-to-one />
    <adm:profile name="ldap">
      <ldap:rdn-sequence>cn=Plugins,cn=config</ldap:rdn-sequence>
    </adm:profile>
    <adm:profile name="cli">
      <cli:relation>
        <cli:default-property name="enabled" />
        <cli:default-property name="plugin-type" />
      </cli:relation>
    </adm:profile>
  </adm:relation>
  <adm:relation name="virtual-attribute">
    <adm:one-to-many />
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;
    }
  }
opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -6694,6 +6694,46 @@
  /**
   * The message ID for the message that will be used if a plugin order
   * definition contains an empty element (i.e., two consecutive commas).  This
   * takes a single argument, which is the name of the plugin type.
   */
  public static final int MSGID_CONFIG_PLUGIN_EMPTY_ELEMENT_IN_ORDER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 664;
  /**
   * The message ID for the message that will be used if a plugin order
   * definition contains multiple wildcard characters.  This takes a single
   * argument, which is the name of the plugin type.
   */
  public static final int MSGID_CONFIG_PLUGIN_MULTIPLE_WILDCARDS_IN_ORDER =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 665;
  /**
   * The message ID for the message that will be used if a plugin is listed
   * multiple times in the plugin order.  This takes two arguments, which are
   * the plugin type and the plugin name.
   */
  public static final int MSGID_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 666;
  /**
   * The message ID for the message that will be used if a plugin order does
   * not contain a wildcard.  This takes a single argument, which is the name of
   * the plugin type.
   */
  public static final int MSGID_CONFIG_PLUGIN_ORDER_NO_WILDCARD =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 667;
  /**
   * Associates a set of generic messages with the message IDs defined in this
@@ -8265,6 +8305,27 @@
                    "instance of class %s as a Directory Server plugin using " +
                    "the information in configuration entry %s:  %s.  This " +
                    "plugin will be disabled");
    registerMessage(MSGID_CONFIG_PLUGIN_EMPTY_ELEMENT_IN_ORDER,
                    "The plugin order definition for plugins of type %s " +
                    "contains an empty element.  This may cause the plugin " +
                    "order to be evaluated incorrectly");
    registerMessage(MSGID_CONFIG_PLUGIN_MULTIPLE_WILDCARDS_IN_ORDER,
                    "The plugin order definition for plugins of type %s " +
                    "contains multiple wildcard characters.  All plugin " +
                    "definitions should contain exactly one wildcard element " +
                    "to indicate where unmatched plugins should be included " +
                    "in the order, and including multiple wildcards may " +
                    "cause the plugin order to be evaluated incorrectly");
    registerMessage(MSGID_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES,
                    "The plugin order definition for plugins of type %s " +
                    "includes multiple references to the '%s' plugin.  This " +
                    "may cause the plugin order to be evaluated incorrectly");
    registerMessage(MSGID_CONFIG_PLUGIN_ORDER_NO_WILDCARD,
                    "The plugin order definition for plugins of type %s " +
                    "does not include a wildcard element to indicate where " +
                    "unmatched plugins should be included in the order.  The " +
                    "server will default to invoking all unnamed plugins " +
                    "after set of named plugins");
    registerMessage(MSGID_CONFIG_PLUGIN_CLASS_ACTION_REQUIRED,
                    "The requested change in the plugin class name from %s " +
                    "to %s in configuration entry %s cannot be dynamically " +
opends/tests/unit-tests-testng/src/server/org/opends/server/core/PluginConfigManagerTestCase.java
New file
@@ -0,0 +1,659 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.plugin.DirectoryServerPlugin;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.types.DN;
import static org.testng.Assert.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * A set of test cases for the plugin config manager.
 */
public class PluginConfigManagerTestCase
       extends CoreTestCase
{
  /**
   * The name of the delay preoperation plugin, formatted in all lowercase.
   */
  private static final String PLUGIN_NAME_DELAY = "delay preoperation plugin";
  /**
   * The name of the disconnect client plugin, formatted in all lowercase.
   */
  private static final String PLUGIN_NAME_DISCONNECT =
       "disconnect client plugin";
  /**
   * The name of the invocation counter plugin, formatted in all lowercase.
   */
  private static final String PLUGIN_NAME_INVOCATION_COUNTER =
       "invocation counter plugin";
  /**
   * The name of the short-circuit plugin, formatted in all lowercase.
   */
  private static final String PLUGIN_NAME_SHORT_CIRCUIT =
       "short circuit plugin";
  /**
   * The name of the update preoperation plugin, formatted in all lowercase.
   */
  private static final String PLUGIN_NAME_UPDATE = "update preoperation plugin";
  /**
   * Ensure that the server is running.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  public void startServer()
         throws Exception
  {
    TestCaseUtils.startServer();
  }
  /**
   * Retrieves a set of data that may be used for testing plugin ordering.  The
   * returned array will be two-dimensional, with the first element being a
   * plugin order string and the second being a string array of the names of the
   * plugins in the order they should appear when using the specified order.
   *
   * @return  A set of data that may be used for testing plugin ordering.
   */
  @DataProvider(name = "pluginOrders")
  public Object[][] getPluginOrders()
  {
    return new Object[][]
    {
      new Object[]
      {
        null,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "*",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "undefined",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "undefined1, undefined2",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "undefined1, *, undefined2",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "undefined, *",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "*, undefined",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DISCONNECT,
        new String[]
        {
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_INVOCATION_COUNTER,
        new String[]
        {
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_SHORT_CIRCUIT,
        new String[]
        {
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY + ", *",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DISCONNECT + ", *",
        new String[]
        {
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_INVOCATION_COUNTER + ", *",
        new String[]
        {
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_SHORT_CIRCUIT + ", *",
        new String[]
        {
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", *",
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_DISCONNECT,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_DISCONNECT
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_INVOCATION_COUNTER,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_INVOCATION_COUNTER
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_SHORT_CIRCUIT,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", *, " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY + ", " + PLUGIN_NAME_DISCONNECT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", " + PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY + ", " + PLUGIN_NAME_DISCONNECT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", " + PLUGIN_NAME_UPDATE + ", *",
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_DELAY + ", " + PLUGIN_NAME_DISCONNECT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", " + PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY + ", " + PLUGIN_NAME_DISCONNECT + ", *, " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", " + PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_DELAY + ", " + PLUGIN_NAME_DISCONNECT + ", undefined, " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", " + PLUGIN_NAME_UPDATE,
        new String[]
        {
          PLUGIN_NAME_DELAY,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_UPDATE
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", " + PLUGIN_NAME_SHORT_CIRCUIT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_DISCONNECT +
             ", " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", " + PLUGIN_NAME_SHORT_CIRCUIT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_DISCONNECT +
             ", " + PLUGIN_NAME_DELAY + ", *",
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        "*, " + PLUGIN_NAME_UPDATE + ", " + PLUGIN_NAME_SHORT_CIRCUIT + ", " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_DISCONNECT +
             ", " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", " + PLUGIN_NAME_SHORT_CIRCUIT + ", *, " +
             PLUGIN_NAME_INVOCATION_COUNTER + ", " + PLUGIN_NAME_DISCONNECT +
             ", " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY
        }
      },
      new Object[]
      {
        PLUGIN_NAME_UPDATE + ", " + PLUGIN_NAME_SHORT_CIRCUIT +
             ", undefined, " + PLUGIN_NAME_INVOCATION_COUNTER + ", " +
             PLUGIN_NAME_DISCONNECT + ", " + PLUGIN_NAME_DELAY,
        new String[]
        {
          PLUGIN_NAME_UPDATE,
          PLUGIN_NAME_SHORT_CIRCUIT,
          PLUGIN_NAME_INVOCATION_COUNTER,
          PLUGIN_NAME_DISCONNECT,
          PLUGIN_NAME_DELAY
        }
      },
    };
  }
  /**
   * Tests the ability of the server to order plugins correctly.
   *
   * @param  pluginOrderString  The string that defines the plugin order to be
   *                            used.
   * @param  expectedNameOrder  An array  of the plugin names in the order they
   *                            are expected to appear when sorted.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider="pluginOrders")
  public void testPluginOrder(String pluginOrderString,
                              String[] expectedNameOrder)
         throws Exception
  {
    String pluginBase = ",cn=Plugins,cn=config";
    ArrayList<DN> dnList = new ArrayList<DN>();
    dnList.add(DN.decode("cn=" + PLUGIN_NAME_DELAY + pluginBase));
    dnList.add(DN.decode("cn=" + PLUGIN_NAME_DISCONNECT + pluginBase));
    dnList.add(DN.decode("cn=" + PLUGIN_NAME_INVOCATION_COUNTER + pluginBase));
    dnList.add(DN.decode("cn=" + PLUGIN_NAME_SHORT_CIRCUIT + pluginBase));
    dnList.add(DN.decode("cn=" + PLUGIN_NAME_UPDATE + pluginBase));
    ArrayList<DirectoryServerPlugin> pluginList =
         new ArrayList<DirectoryServerPlugin>(dnList.size());
    for (DN dn : dnList)
    {
      DirectoryServerPlugin p =
           DirectoryServer.getPluginConfigManager().getRegisteredPlugin(dn);
      assertNotNull(p);
      pluginList.add(p);
    }
    DirectoryServerPlugin[] pluginArray = new DirectoryServerPlugin[0];
    for (DirectoryServerPlugin p : pluginList)
    {
      pluginArray = PluginConfigManager.addPlugin(pluginArray, p,
                                                  PluginType.PRE_OPERATION_ADD,
                                                  pluginOrderString);
    }
    assertEquals(pluginArray.length, expectedNameOrder.length);
    boolean match = true;
    StringBuilder expectedOrder = new StringBuilder();
    StringBuilder actualOrder   = new StringBuilder();
    for (int i=0; i < pluginArray.length; i++)
    {
      if (i > 0)
      {
        expectedOrder.append(", ");
        actualOrder.append(", ");
      }
      expectedOrder.append(expectedNameOrder[i]);
      DN dn = pluginArray[i].getPluginEntryDN();
      String name =
           dn.getRDN().getAttributeValue(0).getStringValue().toLowerCase();
      actualOrder.append(name);
      if (! name.equals(expectedNameOrder[i]))
      {
        match = false;
      }
    }
    assertTrue(match,
               EOL + "Expected order:  " + expectedOrder.toString() + EOL +
               "Actual order:    " + actualOrder.toString());
  }
}