001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.core;
028    
029    
030    
031    import java.lang.reflect.Method;
032    import java.util.ArrayList;
033    import java.util.HashMap;
034    import java.util.HashSet;
035    import java.util.Iterator;
036    import java.util.LinkedHashSet;
037    import java.util.List;
038    import java.util.Set;
039    import java.util.StringTokenizer;
040    import java.util.concurrent.ConcurrentHashMap;
041    import java.util.concurrent.locks.ReentrantLock;
042    
043    import org.opends.messages.Message;
044    import org.opends.messages.MessageBuilder;
045    import org.opends.server.admin.ClassPropertyDefinition;
046    import org.opends.server.admin.server.ConfigurationAddListener;
047    import org.opends.server.admin.server.ConfigurationChangeListener;
048    import org.opends.server.admin.server.ConfigurationDeleteListener;
049    import org.opends.server.admin.server.ServerManagementContext;
050    import org.opends.server.admin.std.meta.PluginCfgDefn;
051    import org.opends.server.admin.std.server.PluginCfg;
052    import org.opends.server.admin.std.server.PluginRootCfg;
053    import org.opends.server.admin.std.server.RootCfg;
054    import org.opends.server.api.ClientConnection;
055    import org.opends.server.api.plugin.*;
056    import org.opends.server.config.ConfigException;
057    import org.opends.server.loggers.debug.DebugTracer;
058    import org.opends.server.types.*;
059    import org.opends.server.types.operation.*;
060    import org.opends.server.workflowelement.localbackend.*;
061    
062    import static org.opends.messages.ConfigMessages.*;
063    import static org.opends.messages.PluginMessages.*;
064    import static org.opends.server.loggers.debug.DebugLogger.*;
065    import static org.opends.server.loggers.ErrorLogger.*;
066    import static org.opends.server.util.StaticUtils.*;
067    
068    
069    
070    /**
071     * This class defines a utility that will be used to manage the configuration
072     * for the set of plugins defined in the Directory Server.  It will perform the
073     * necessary initialization of those plugins when the server is first started,
074     * and then will manage any changes to them while the server is running.  It
075     * also provides methods for invoking all the plugins of a given type.
076     */
077    public class PluginConfigManager
078           implements ConfigurationAddListener<PluginCfg>,
079                      ConfigurationDeleteListener<PluginCfg>,
080                      ConfigurationChangeListener<PluginCfg>
081    {
082      /**
083       * The tracer object for the debug logger.
084       */
085      private static final DebugTracer TRACER = getTracer();
086    
087      // Arrays for holding the plugins of each type.
088      private DirectoryServerPlugin[] startupPlugins;
089      private DirectoryServerPlugin[] shutdownPlugins;
090      private DirectoryServerPlugin[] postConnectPlugins;
091      private DirectoryServerPlugin[] postDisconnectPlugins;
092      private DirectoryServerPlugin[] ldifImportPlugins;
093      private DirectoryServerPlugin[] ldifExportPlugins;
094      private DirectoryServerPlugin[] preParseAbandonPlugins;
095      private DirectoryServerPlugin[] preParseAddPlugins;
096      private DirectoryServerPlugin[] preParseBindPlugins;
097      private DirectoryServerPlugin[] preParseComparePlugins;
098      private DirectoryServerPlugin[] preParseDeletePlugins;
099      private DirectoryServerPlugin[] preParseExtendedPlugins;
100      private DirectoryServerPlugin[] preParseModifyPlugins;
101      private DirectoryServerPlugin[] preParseModifyDNPlugins;
102      private DirectoryServerPlugin[] preParseSearchPlugins;
103      private DirectoryServerPlugin[] preParseUnbindPlugins;
104      private DirectoryServerPlugin[] preOperationAddPlugins;
105      private DirectoryServerPlugin[] preOperationBindPlugins;
106      private DirectoryServerPlugin[] preOperationComparePlugins;
107      private DirectoryServerPlugin[] preOperationDeletePlugins;
108      private DirectoryServerPlugin[] preOperationExtendedPlugins;
109      private DirectoryServerPlugin[] preOperationModifyPlugins;
110      private DirectoryServerPlugin[] preOperationModifyDNPlugins;
111      private DirectoryServerPlugin[] preOperationSearchPlugins;
112      private DirectoryServerPlugin[] postOperationAbandonPlugins;
113      private DirectoryServerPlugin[] postOperationAddPlugins;
114      private DirectoryServerPlugin[] postOperationBindPlugins;
115      private DirectoryServerPlugin[] postOperationComparePlugins;
116      private DirectoryServerPlugin[] postOperationDeletePlugins;
117      private DirectoryServerPlugin[] postOperationExtendedPlugins;
118      private DirectoryServerPlugin[] postOperationModifyPlugins;
119      private DirectoryServerPlugin[] postOperationModifyDNPlugins;
120      private DirectoryServerPlugin[] postOperationSearchPlugins;
121      private DirectoryServerPlugin[] postOperationUnbindPlugins;
122      private DirectoryServerPlugin[] postResponseAddPlugins;
123      private DirectoryServerPlugin[] postResponseBindPlugins;
124      private DirectoryServerPlugin[] postResponseComparePlugins;
125      private DirectoryServerPlugin[] postResponseDeletePlugins;
126      private DirectoryServerPlugin[] postResponseExtendedPlugins;
127      private DirectoryServerPlugin[] postResponseModifyPlugins;
128      private DirectoryServerPlugin[] postResponseModifyDNPlugins;
129      private DirectoryServerPlugin[] postResponseSearchPlugins;
130      private DirectoryServerPlugin[] postSynchronizationAddPlugins;
131      private DirectoryServerPlugin[] postSynchronizationDeletePlugins;
132      private DirectoryServerPlugin[] postSynchronizationModifyPlugins;
133      private DirectoryServerPlugin[] postSynchronizationModifyDNPlugins;
134      private DirectoryServerPlugin[] searchResultEntryPlugins;
135      private DirectoryServerPlugin[] searchResultReferencePlugins;
136      private DirectoryServerPlugin[] subordinateModifyDNPlugins;
137      private DirectoryServerPlugin[] intermediateResponsePlugins;
138    
139    
140      // The mapping between the DN of a plugin entry and the plugin instance loaded
141      // from that entry.
142      private ConcurrentHashMap<DN,
143                   DirectoryServerPlugin<? extends PluginCfg>>
144                        registeredPlugins;
145    
146      // The mapping between an operation and a set of post operation plugins
147      // it should skip. This pairs up pre and post operation plugin processing
148      // such that only plugins that successfully execute its pre op plugin will
149      // have its post op plugin executed on a per operation basis. If an
150      // operation is not registered on this list then all all pre op plugins
151      // executed successfully for this operation so all post op plugins should
152      // execute.
153      private ConcurrentHashMap<PluginOperation, ArrayList<DirectoryServerPlugin>>
154          skippedPreOperationPlugins;
155    
156      // The plugin root configuration read at server startup.
157      private PluginRootCfg pluginRootConfig;
158    
159      // The lock that will provide threadsafe access to the sets of registered
160      // plugins.
161      private ReentrantLock pluginLock;
162    
163    
164    
165      /**
166       * Creates a new instance of this plugin config manager.
167       */
168      public PluginConfigManager()
169      {
170        pluginLock = new ReentrantLock();
171    
172        startupPlugins                     = new DirectoryServerPlugin[0];
173        shutdownPlugins                    = new DirectoryServerPlugin[0];
174        postConnectPlugins                 = new DirectoryServerPlugin[0];
175        postDisconnectPlugins              = new DirectoryServerPlugin[0];
176        ldifImportPlugins                  = new DirectoryServerPlugin[0];
177        ldifExportPlugins                  = new DirectoryServerPlugin[0];
178        preParseAbandonPlugins             = new DirectoryServerPlugin[0];
179        preParseAddPlugins                 = new DirectoryServerPlugin[0];
180        preParseBindPlugins                = new DirectoryServerPlugin[0];
181        preParseComparePlugins             = new DirectoryServerPlugin[0];
182        preParseDeletePlugins              = new DirectoryServerPlugin[0];
183        preParseExtendedPlugins            = new DirectoryServerPlugin[0];
184        preParseModifyPlugins              = new DirectoryServerPlugin[0];
185        preParseModifyDNPlugins            = new DirectoryServerPlugin[0];
186        preParseSearchPlugins              = new DirectoryServerPlugin[0];
187        preParseUnbindPlugins              = new DirectoryServerPlugin[0];
188        preOperationAddPlugins             = new DirectoryServerPlugin[0];
189        preOperationBindPlugins            = new DirectoryServerPlugin[0];
190        preOperationComparePlugins         = new DirectoryServerPlugin[0];
191        preOperationDeletePlugins          = new DirectoryServerPlugin[0];
192        preOperationExtendedPlugins        = new DirectoryServerPlugin[0];
193        preOperationModifyPlugins          = new DirectoryServerPlugin[0];
194        preOperationModifyDNPlugins        = new DirectoryServerPlugin[0];
195        preOperationSearchPlugins          = new DirectoryServerPlugin[0];
196        postOperationAbandonPlugins        = new DirectoryServerPlugin[0];
197        postOperationAddPlugins            = new DirectoryServerPlugin[0];
198        postOperationBindPlugins           = new DirectoryServerPlugin[0];
199        postOperationComparePlugins        = new DirectoryServerPlugin[0];
200        postOperationDeletePlugins         = new DirectoryServerPlugin[0];
201        postOperationExtendedPlugins       = new DirectoryServerPlugin[0];
202        postOperationModifyPlugins         = new DirectoryServerPlugin[0];
203        postOperationModifyDNPlugins       = new DirectoryServerPlugin[0];
204        postOperationSearchPlugins         = new DirectoryServerPlugin[0];
205        postOperationUnbindPlugins         = new DirectoryServerPlugin[0];
206        postResponseAddPlugins             = new DirectoryServerPlugin[0];
207        postResponseBindPlugins            = new DirectoryServerPlugin[0];
208        postResponseComparePlugins         = new DirectoryServerPlugin[0];
209        postResponseDeletePlugins          = new DirectoryServerPlugin[0];
210        postResponseExtendedPlugins        = new DirectoryServerPlugin[0];
211        postResponseModifyPlugins          = new DirectoryServerPlugin[0];
212        postResponseModifyDNPlugins        = new DirectoryServerPlugin[0];
213        postResponseSearchPlugins          = new DirectoryServerPlugin[0];
214        postSynchronizationAddPlugins      = new DirectoryServerPlugin[0];
215        postSynchronizationDeletePlugins   = new DirectoryServerPlugin[0];
216        postSynchronizationModifyPlugins   = new DirectoryServerPlugin[0];
217        postSynchronizationModifyDNPlugins = new DirectoryServerPlugin[0];
218        searchResultEntryPlugins           = new DirectoryServerPlugin[0];
219        searchResultReferencePlugins       = new DirectoryServerPlugin[0];
220        subordinateModifyDNPlugins         = new DirectoryServerPlugin[0];
221        intermediateResponsePlugins        = new DirectoryServerPlugin[0];
222        registeredPlugins                  =
223             new ConcurrentHashMap<DN,
224                      DirectoryServerPlugin<? extends PluginCfg>>();
225        skippedPreOperationPlugins =
226            new ConcurrentHashMap<PluginOperation,
227                      ArrayList<DirectoryServerPlugin>>();
228      }
229    
230    
231    
232      /**
233       * Initializes the configuration associated with the Directory Server plugins.
234       * This should only be called at Directory Server startup.
235       *
236       * @param  pluginTypes  The set of plugin types for the plugins to initialize,
237       *                      or <CODE>null</CODE> to initialize all types of
238       *                      plugins defined in the server configuration.  In
239       *                      general, this should only be non-null for cases in
240       *                      which the server is running in a special mode that
241       *                      only uses a minimal set of plugins (e.g., LDIF import
242       *                      or export).
243       *
244       * @throws  ConfigException  If a critical configuration problem prevents the
245       *                           plugin initialization from succeeding.
246       *
247       * @throws  InitializationException  If a problem occurs while initializing
248       *                                   the plugins that is not related to the
249       *                                   server configuration.
250       */
251      public void initializePluginConfig(Set<PluginType> pluginTypes)
252             throws ConfigException, InitializationException
253      {
254        registeredPlugins.clear();
255    
256    
257        // Get the root configuration object.
258        ServerManagementContext managementContext =
259             ServerManagementContext.getInstance();
260        RootCfg rootConfiguration =
261             managementContext.getRootConfiguration();
262    
263    
264        // Get the plugin root configuration and register with it as an add and
265        // delete listener so we can be notified if any plugin entries are added or
266        // removed.
267        pluginRootConfig = rootConfiguration.getPluginRoot();
268        pluginRootConfig.addPluginAddListener(this);
269        pluginRootConfig.addPluginDeleteListener(this);
270    
271    
272        //Initialize the existing plugins.
273        for (String pluginName : pluginRootConfig.listPlugins())
274        {
275          PluginCfg pluginConfiguration = pluginRootConfig.getPlugin(pluginName);
276          pluginConfiguration.addChangeListener(this);
277    
278          if (! pluginConfiguration.isEnabled())
279          {
280            continue;
281          }
282    
283          // Create a set of plugin types for the plugin.
284          HashSet<PluginType> initTypes = new HashSet<PluginType>();
285          for (PluginCfgDefn.PluginType pluginType :
286               pluginConfiguration.getPluginType())
287          {
288            PluginType t = getPluginType(pluginType);
289            if ((pluginTypes == null) || pluginTypes.contains(t))
290            {
291              initTypes.add(t);
292            }
293          }
294    
295          if (initTypes.isEmpty())
296          {
297            continue;
298          }
299    
300          try
301          {
302            DirectoryServerPlugin<? extends PluginCfg> plugin =
303                 loadPlugin(pluginConfiguration.getJavaClass(), initTypes,
304                            pluginConfiguration, true);
305            registerPlugin(plugin, pluginConfiguration.dn(), initTypes);
306          }
307          catch (InitializationException ie)
308          {
309            logError(ie.getMessageObject());
310            continue;
311          }
312        }
313      }
314    
315    
316    
317      /**
318       * Loads the specified class, instantiates it as a plugin, and optionally
319       * initializes that plugin.
320       *
321       * @param  className      The fully-qualified name of the plugin class to
322       *                        load, instantiate, and initialize.
323       * @param  pluginTypes    The set of plugin types for the plugins to
324       *                        initialize, or {@code null} to initialize all types
325       *                        of plugins defined in the server configuration.  In
326       *                        general, this should only be non-null for cases in
327       *                        which the server is running in a special mode that
328       *                        only uses a minimal set of plugins (e.g., LDIF
329       *                        import or export).
330       * @param  configuration  The configuration to use to initialize the plugin.
331       *                        It must not be {@code null}.
332       * @param  initialize     Indicates whether the plugin instance should be
333       *                        initialized.
334       *
335       * @return  The possibly initialized plugin.
336       *
337       * @throws  InitializationException  If a problem occurred while attempting to
338       *                                   initialize the plugin.
339       */
340      private DirectoryServerPlugin<? extends PluginCfg>
341                   loadPlugin(String className, Set<PluginType> pluginTypes,
342                              PluginCfg configuration, boolean initialize)
343              throws InitializationException
344      {
345        try
346        {
347          PluginCfgDefn definition =
348               PluginCfgDefn.getInstance();
349          ClassPropertyDefinition propertyDefinition =
350               definition.getJavaClassPropertyDefinition();
351          Class<? extends DirectoryServerPlugin> pluginClass =
352               propertyDefinition.loadClass(className, DirectoryServerPlugin.class);
353          DirectoryServerPlugin<? extends PluginCfg> plugin =
354               (DirectoryServerPlugin<? extends PluginCfg>)
355               pluginClass.newInstance();
356    
357          if (initialize)
358          {
359            Method method = plugin.getClass().getMethod("initializeInternal",
360                                                        PluginCfg.class, Set.class);
361            method.invoke(plugin, configuration, pluginTypes);
362    
363            method = plugin.getClass().getMethod("initializePlugin", Set.class,
364                configuration.configurationClass());
365            method.invoke(plugin, pluginTypes, configuration);
366          }
367          else
368          {
369            Method method = plugin.getClass().getMethod("isConfigurationAcceptable",
370                                                        PluginCfg.class,
371                                                        List.class);
372    
373            List<Message> unacceptableReasons = new ArrayList<Message>();
374            Boolean acceptable = (Boolean) method.invoke(plugin, configuration,
375                                                         unacceptableReasons);
376            if (! acceptable)
377            {
378              MessageBuilder buffer = new MessageBuilder();
379              if (! unacceptableReasons.isEmpty())
380              {
381                Iterator<Message> iterator = unacceptableReasons.iterator();
382                buffer.append(iterator.next());
383                while (iterator.hasNext())
384                {
385                  buffer.append(".  ");
386                  buffer.append(iterator.next());
387                }
388              }
389    
390              Message message = ERR_CONFIG_PLUGIN_CONFIG_NOT_ACCEPTABLE.get(
391                  String.valueOf(configuration.dn()), buffer.toString());
392              throw new InitializationException(message);
393            }
394          }
395    
396          return plugin;
397        }
398        catch (Exception e)
399        {
400          Message message = ERR_CONFIG_PLUGIN_CANNOT_INITIALIZE.
401              get(className, String.valueOf(configuration.dn()),
402                  stackTraceToSingleLineString(e));
403          throw new InitializationException(message, e);
404        }
405      }
406    
407    
408    
409      /**
410       * Gets the OpenDS plugin type object that corresponds to the configuration
411       * counterpart.
412       *
413       * @param  configPluginType  The configuration plugin type for which to
414       *                           retrieve the OpenDS plugin type.
415       */
416      private PluginType getPluginType(PluginCfgDefn.PluginType
417                                            configPluginType)
418      {
419        switch (configPluginType)
420        {
421          case STARTUP:                return PluginType.STARTUP;
422          case SHUTDOWN:               return PluginType.SHUTDOWN;
423          case POSTCONNECT:            return PluginType.POST_CONNECT;
424          case POSTDISCONNECT:         return PluginType.POST_DISCONNECT;
425          case LDIFIMPORT:             return PluginType.LDIF_IMPORT;
426          case LDIFEXPORT:             return PluginType.LDIF_EXPORT;
427          case PREPARSEABANDON:        return PluginType.PRE_PARSE_ABANDON;
428          case PREPARSEADD:            return PluginType.PRE_PARSE_ADD;
429          case PREPARSEBIND:           return PluginType.PRE_PARSE_BIND;
430          case PREPARSECOMPARE:        return PluginType.PRE_PARSE_COMPARE;
431          case PREPARSEDELETE:         return PluginType.PRE_PARSE_DELETE;
432          case PREPARSEEXTENDED:       return PluginType.PRE_PARSE_EXTENDED;
433          case PREPARSEMODIFY:         return PluginType.PRE_PARSE_MODIFY;
434          case PREPARSEMODIFYDN:       return PluginType.PRE_PARSE_MODIFY_DN;
435          case PREPARSESEARCH:         return PluginType.PRE_PARSE_SEARCH;
436          case PREPARSEUNBIND:         return PluginType.PRE_PARSE_UNBIND;
437          case PREOPERATIONADD:        return PluginType.PRE_OPERATION_ADD;
438          case PREOPERATIONBIND:       return PluginType.PRE_OPERATION_BIND;
439          case PREOPERATIONCOMPARE:    return PluginType.PRE_OPERATION_COMPARE;
440          case PREOPERATIONDELETE:     return PluginType.PRE_OPERATION_DELETE;
441          case PREOPERATIONEXTENDED:   return PluginType.PRE_OPERATION_EXTENDED;
442          case PREOPERATIONMODIFY:     return PluginType.PRE_OPERATION_MODIFY;
443          case PREOPERATIONMODIFYDN:   return PluginType.PRE_OPERATION_MODIFY_DN;
444          case PREOPERATIONSEARCH:     return PluginType.PRE_OPERATION_SEARCH;
445          case POSTOPERATIONABANDON:   return PluginType.POST_OPERATION_ABANDON;
446          case POSTOPERATIONADD:       return PluginType.POST_OPERATION_ADD;
447          case POSTOPERATIONBIND:      return PluginType.POST_OPERATION_BIND;
448          case POSTOPERATIONCOMPARE:   return PluginType.POST_OPERATION_COMPARE;
449          case POSTOPERATIONDELETE:    return PluginType.POST_OPERATION_DELETE;
450          case POSTOPERATIONEXTENDED:  return PluginType.POST_OPERATION_EXTENDED;
451          case POSTOPERATIONMODIFY:    return PluginType.POST_OPERATION_MODIFY;
452          case POSTOPERATIONMODIFYDN:  return PluginType.POST_OPERATION_MODIFY_DN;
453          case POSTOPERATIONSEARCH:    return PluginType.POST_OPERATION_SEARCH;
454          case POSTOPERATIONUNBIND:    return PluginType.POST_OPERATION_UNBIND;
455          case POSTRESPONSEADD:        return PluginType.POST_RESPONSE_ADD;
456          case POSTRESPONSEBIND:       return PluginType.POST_RESPONSE_BIND;
457          case POSTRESPONSECOMPARE:    return PluginType.POST_RESPONSE_COMPARE;
458          case POSTRESPONSEDELETE:     return PluginType.POST_RESPONSE_DELETE;
459          case POSTRESPONSEEXTENDED:   return PluginType.POST_RESPONSE_EXTENDED;
460          case POSTRESPONSEMODIFY:     return PluginType.POST_RESPONSE_MODIFY;
461          case POSTRESPONSEMODIFYDN:   return PluginType.POST_RESPONSE_MODIFY_DN;
462          case POSTRESPONSESEARCH:     return PluginType.POST_RESPONSE_SEARCH;
463          case SEARCHRESULTENTRY:      return PluginType.SEARCH_RESULT_ENTRY;
464          case SEARCHRESULTREFERENCE:  return PluginType.SEARCH_RESULT_REFERENCE;
465          case SUBORDINATEMODIFYDN:    return PluginType.SUBORDINATE_MODIFY_DN;
466          case INTERMEDIATERESPONSE:   return PluginType.INTERMEDIATE_RESPONSE;
467          case POSTSYNCHRONIZATIONADD:
468                    return PluginType.POST_SYNCHRONIZATION_ADD;
469          case POSTSYNCHRONIZATIONDELETE:
470                    return PluginType.POST_SYNCHRONIZATION_DELETE;
471          case POSTSYNCHRONIZATIONMODIFY:
472                    return PluginType.POST_SYNCHRONIZATION_MODIFY;
473          case POSTSYNCHRONIZATIONMODIFYDN:
474                    return PluginType.POST_SYNCHRONIZATION_MODIFY_DN;
475          default:                     return null;
476        }
477      }
478    
479    
480    
481      /**
482       * Finalizes all plugins that are registered with the Directory Server.
483       */
484      public void finalizePlugins()
485      {
486        pluginLock.lock();
487    
488        try
489        {
490          Iterator<DirectoryServerPlugin<? extends PluginCfg>> iterator =
491               registeredPlugins.values().iterator();
492          while (iterator.hasNext())
493          {
494            try
495            {
496              iterator.next().finalizePlugin();
497            }
498            catch (Exception e)
499            {
500              if (debugEnabled())
501              {
502                TRACER.debugCaught(DebugLogLevel.ERROR, e);
503              }
504            }
505          }
506    
507          registeredPlugins.clear();
508        }
509        finally
510        {
511          pluginLock.unlock();
512        }
513      }
514    
515    
516    
517      /**
518       * Retrieves the set of plugins that have been registered with the Directory
519       * Server.
520       *
521       * @return  The set of plugins that have been registered with the Directory
522       *          Server.
523       */
524      public ConcurrentHashMap<DN,
525                  DirectoryServerPlugin<? extends PluginCfg>>
526                       getRegisteredPlugins()
527      {
528        return registeredPlugins;
529      }
530    
531    
532    
533      /**
534       * Retrieves the plugin with the specified configuration entry DN.
535       *
536       * @param  pluginDN  The DN of the configuration entry for the plugin to
537       *                   retrieve.
538       *
539       * @return  The requested plugin, or <CODE>null</CODE> if there is no such
540       *          plugin.
541       */
542      public DirectoryServerPlugin getRegisteredPlugin(DN pluginDN)
543      {
544        return registeredPlugins.get(pluginDN);
545      }
546    
547    
548    
549      /**
550       * Registers the provided plugin with this plugin config manager and ensures
551       * that it will be invoked in the specified ways.
552       *
553       * @param  plugin         The plugin to register with the server.
554       * @param  pluginEntryDN  The DN of the configuration entry for the provided
555       *                        plugin.
556       * @param  pluginTypes    The plugin types that will be used to control the
557       *                        points at which the provided plugin is invoked.
558       */
559      private void registerPlugin(
560                        DirectoryServerPlugin<? extends PluginCfg> plugin,
561                        DN pluginEntryDN, Set<PluginType> pluginTypes)
562      {
563        pluginLock.lock();
564    
565        try
566        {
567          registeredPlugins.put(pluginEntryDN, plugin);
568    
569          for (PluginType t : pluginTypes)
570          {
571            switch (t)
572            {
573              case STARTUP:
574                startupPlugins =
575                     addPlugin(startupPlugins, plugin, t,
576                               pluginRootConfig.getPluginOrderStartup());
577                break;
578              case SHUTDOWN:
579                shutdownPlugins =
580                     addPlugin(shutdownPlugins, plugin, t,
581                               pluginRootConfig.getPluginOrderShutdown());
582                break;
583              case POST_CONNECT:
584                postConnectPlugins =
585                     addPlugin(postConnectPlugins, plugin, t,
586                               pluginRootConfig.getPluginOrderPostConnect());
587                break;
588              case POST_DISCONNECT:
589                postDisconnectPlugins =
590                     addPlugin(postDisconnectPlugins, plugin, t,
591                               pluginRootConfig.getPluginOrderPostDisconnect());
592                break;
593              case LDIF_IMPORT:
594                ldifImportPlugins =
595                     addPlugin(ldifImportPlugins, plugin, t,
596                               pluginRootConfig.getPluginOrderLDIFImport());
597                break;
598              case LDIF_EXPORT:
599                ldifExportPlugins =
600                     addPlugin(ldifExportPlugins, plugin, t,
601                               pluginRootConfig.getPluginOrderLDIFExport());
602                break;
603              case PRE_PARSE_ABANDON:
604                preParseAbandonPlugins =
605                     addPlugin(preParseAbandonPlugins, plugin, t,
606                               pluginRootConfig.getPluginOrderPreParseAbandon());
607                break;
608              case PRE_PARSE_ADD:
609                preParseAddPlugins =
610                     addPlugin(preParseAddPlugins, plugin, t,
611                               pluginRootConfig.getPluginOrderPreParseAdd());
612                break;
613              case PRE_PARSE_BIND:
614                preParseBindPlugins =
615                     addPlugin(preParseBindPlugins, plugin, t,
616                               pluginRootConfig.getPluginOrderPreParseBind());
617                break;
618              case PRE_PARSE_COMPARE:
619                preParseComparePlugins =
620                     addPlugin(preParseComparePlugins, plugin, t,
621                               pluginRootConfig.getPluginOrderPreParseCompare());
622                break;
623              case PRE_PARSE_DELETE:
624                preParseDeletePlugins =
625                     addPlugin(preParseDeletePlugins, plugin, t,
626                               pluginRootConfig.getPluginOrderPreParseDelete());
627                break;
628              case PRE_PARSE_EXTENDED:
629                preParseExtendedPlugins =
630                     addPlugin(preParseExtendedPlugins, plugin, t,
631                               pluginRootConfig.getPluginOrderPreParseExtended());
632                break;
633              case PRE_PARSE_MODIFY:
634                preParseModifyPlugins =
635                     addPlugin(preParseModifyPlugins, plugin, t,
636                               pluginRootConfig.getPluginOrderPreParseModify());
637                break;
638              case PRE_PARSE_MODIFY_DN:
639                preParseModifyDNPlugins =
640                     addPlugin(preParseModifyDNPlugins, plugin, t,
641                               pluginRootConfig.getPluginOrderPreParseModifyDN());
642                break;
643              case PRE_PARSE_SEARCH:
644                preParseSearchPlugins =
645                     addPlugin(preParseSearchPlugins, plugin, t,
646                               pluginRootConfig.getPluginOrderPreParseSearch());
647                break;
648              case PRE_PARSE_UNBIND:
649                preParseUnbindPlugins =
650                     addPlugin(preParseUnbindPlugins, plugin, t,
651                               pluginRootConfig.getPluginOrderPreParseUnbind());
652                break;
653              case PRE_OPERATION_ADD:
654                preOperationAddPlugins =
655                     addPlugin(preOperationAddPlugins, plugin, t,
656                               pluginRootConfig.getPluginOrderPreOperationAdd());
657                break;
658              case PRE_OPERATION_BIND:
659                preOperationBindPlugins =
660                     addPlugin(preOperationBindPlugins, plugin, t,
661                               pluginRootConfig.getPluginOrderPreOperationBind());
662                break;
663              case PRE_OPERATION_COMPARE:
664                preOperationComparePlugins =
665                     addPlugin(preOperationComparePlugins,plugin, t,
666                          pluginRootConfig.getPluginOrderPreOperationCompare());
667                break;
668              case PRE_OPERATION_DELETE:
669                preOperationDeletePlugins =
670                     addPlugin(preOperationDeletePlugins, plugin, t,
671                               pluginRootConfig.getPluginOrderPreOperationDelete());
672                break;
673              case PRE_OPERATION_EXTENDED:
674                preOperationExtendedPlugins =
675                     addPlugin(preOperationExtendedPlugins, plugin, t,
676                          pluginRootConfig.getPluginOrderPreOperationExtended());
677                break;
678              case PRE_OPERATION_MODIFY:
679                preOperationModifyPlugins =
680                     addPlugin(preOperationModifyPlugins, plugin, t,
681                               pluginRootConfig.getPluginOrderPreOperationModify());
682                break;
683              case PRE_OPERATION_MODIFY_DN:
684                preOperationModifyDNPlugins =
685                     addPlugin(preOperationModifyDNPlugins, plugin, t,
686                          pluginRootConfig.getPluginOrderPreOperationModifyDN());
687                break;
688              case PRE_OPERATION_SEARCH:
689                preOperationSearchPlugins =
690                     addPlugin(preOperationSearchPlugins, plugin, t,
691                               pluginRootConfig.getPluginOrderPreOperationSearch());
692                break;
693              case POST_OPERATION_ABANDON:
694                postOperationAbandonPlugins =
695                     addPlugin(postOperationAbandonPlugins, plugin, t,
696                          pluginRootConfig.getPluginOrderPostOperationAbandon());
697                break;
698              case POST_OPERATION_ADD:
699                postOperationAddPlugins =
700                     addPlugin(postOperationAddPlugins, plugin, t,
701                               pluginRootConfig.getPluginOrderPostOperationAdd());
702                break;
703              case POST_OPERATION_BIND:
704                postOperationBindPlugins =
705                     addPlugin(postOperationBindPlugins, plugin, t,
706                               pluginRootConfig.getPluginOrderPostOperationBind());
707                break;
708              case POST_OPERATION_COMPARE:
709                postOperationComparePlugins =
710                     addPlugin(postOperationComparePlugins, plugin, t,
711                          pluginRootConfig.getPluginOrderPostOperationCompare());
712                break;
713              case POST_OPERATION_DELETE:
714                postOperationDeletePlugins =
715                     addPlugin(postOperationDeletePlugins, plugin, t,
716                          pluginRootConfig.getPluginOrderPostOperationDelete());
717                break;
718              case POST_OPERATION_EXTENDED:
719                postOperationExtendedPlugins =
720                     addPlugin(postOperationExtendedPlugins, plugin, t,
721                          pluginRootConfig.getPluginOrderPostOperationExtended());
722                break;
723              case POST_OPERATION_MODIFY:
724                postOperationModifyPlugins =
725                     addPlugin(postOperationModifyPlugins, plugin, t,
726                          pluginRootConfig.getPluginOrderPostOperationModify());
727                break;
728              case POST_OPERATION_MODIFY_DN:
729                postOperationModifyDNPlugins =
730                     addPlugin(postOperationModifyDNPlugins, plugin, t,
731                          pluginRootConfig.getPluginOrderPostOperationModifyDN());
732                break;
733              case POST_OPERATION_SEARCH:
734                postOperationSearchPlugins =
735                     addPlugin(postOperationSearchPlugins, plugin, t,
736                          pluginRootConfig.getPluginOrderPostOperationSearch());
737                break;
738              case POST_OPERATION_UNBIND:
739                postOperationUnbindPlugins =
740                     addPlugin(postOperationUnbindPlugins, plugin, t,
741                          pluginRootConfig.getPluginOrderPostOperationUnbind());
742                break;
743              case POST_RESPONSE_ADD:
744                postResponseAddPlugins =
745                     addPlugin(postResponseAddPlugins, plugin, t,
746                               pluginRootConfig.getPluginOrderPostResponseAdd());
747                break;
748              case POST_RESPONSE_BIND:
749                postResponseBindPlugins =
750                     addPlugin(postResponseBindPlugins, plugin, t,
751                               pluginRootConfig.getPluginOrderPostResponseBind());
752                break;
753              case POST_RESPONSE_COMPARE:
754                postResponseComparePlugins =
755                     addPlugin(postResponseComparePlugins, plugin, t,
756                          pluginRootConfig.getPluginOrderPostResponseCompare());
757                break;
758              case POST_RESPONSE_DELETE:
759                postResponseDeletePlugins =
760                     addPlugin(postResponseDeletePlugins, plugin, t,
761                               pluginRootConfig.getPluginOrderPostResponseDelete());
762                break;
763              case POST_RESPONSE_EXTENDED:
764                postResponseExtendedPlugins =
765                     addPlugin(postResponseExtendedPlugins, plugin, t,
766                          pluginRootConfig.getPluginOrderPostResponseExtended());
767                break;
768              case POST_RESPONSE_MODIFY:
769                postResponseModifyPlugins =
770                     addPlugin(postResponseModifyPlugins, plugin, t,
771                               pluginRootConfig.getPluginOrderPostResponseModify());
772                break;
773              case POST_RESPONSE_MODIFY_DN:
774                postResponseModifyDNPlugins =
775                     addPlugin(postResponseModifyDNPlugins, plugin, t,
776                          pluginRootConfig.getPluginOrderPostResponseModifyDN());
777                break;
778              case POST_RESPONSE_SEARCH:
779                postResponseSearchPlugins =
780                     addPlugin(postResponseSearchPlugins, plugin, t,
781                               pluginRootConfig.getPluginOrderPostResponseSearch());
782                break;
783              case POST_SYNCHRONIZATION_ADD:
784                postSynchronizationAddPlugins =
785                     addPlugin(postSynchronizationAddPlugins, plugin, t,
786                               pluginRootConfig.
787                                    getPluginOrderPostSynchronizationAdd());
788                break;
789              case POST_SYNCHRONIZATION_DELETE:
790                postSynchronizationDeletePlugins =
791                     addPlugin(postSynchronizationDeletePlugins, plugin, t,
792                               pluginRootConfig.
793                                    getPluginOrderPostSynchronizationDelete());
794                break;
795              case POST_SYNCHRONIZATION_MODIFY:
796                postSynchronizationModifyPlugins =
797                     addPlugin(postSynchronizationModifyPlugins, plugin, t,
798                               pluginRootConfig.
799                                    getPluginOrderPostSynchronizationModify());
800                break;
801              case POST_SYNCHRONIZATION_MODIFY_DN:
802                postSynchronizationModifyDNPlugins =
803                     addPlugin(postSynchronizationModifyDNPlugins, plugin, t,
804                               pluginRootConfig.
805                                    getPluginOrderPostSynchronizationModifyDN());
806                break;
807              case SEARCH_RESULT_ENTRY:
808                searchResultEntryPlugins =
809                     addPlugin(searchResultEntryPlugins, plugin, t,
810                               pluginRootConfig.getPluginOrderSearchResultEntry());
811                break;
812              case SEARCH_RESULT_REFERENCE:
813                searchResultReferencePlugins =
814                     addPlugin(searchResultReferencePlugins, plugin, t,
815                          pluginRootConfig.getPluginOrderSearchResultReference());
816                break;
817              case SUBORDINATE_MODIFY_DN:
818                subordinateModifyDNPlugins =
819                     addPlugin(subordinateModifyDNPlugins, plugin, t,
820                          pluginRootConfig.getPluginOrderSubordinateModifyDN());
821                break;
822              case INTERMEDIATE_RESPONSE:
823                intermediateResponsePlugins =
824                     addPlugin(intermediateResponsePlugins, plugin, t,
825                          pluginRootConfig.getPluginOrderIntermediateResponse());
826                break;
827              default:
828            }
829          }
830        }
831        finally
832        {
833          pluginLock.unlock();
834        }
835      }
836    
837    
838    
839      /**
840       * Adds the provided plugin to the given array.  The provided array will not
841       * itself be modified, but rather a new array will be created with one
842       * additional element.  The provided plugin will be the last element in the
843       * new array.
844       * <BR><BR>
845       * Note that the only use of this method outside of this class should be for
846       * testing purposes.
847       *
848       * @param  pluginArray  The array containing the existing set of plugins.
849       * @param  plugin       The plugin to be added to the array.
850       * @param  pluginType   The plugin type for the plugin being registered.
851       * @param  pluginOrder  A string that represents the order in which plugins of
852       *                      this type should be invoked, or {@code null} if the
853       *                      order is not considered important.
854       *
855       * @return  The new array containing the new set of plugins.
856       */
857      static DirectoryServerPlugin[] addPlugin(DirectoryServerPlugin[] pluginArray,
858                                               DirectoryServerPlugin plugin,
859                                               PluginType pluginType,
860                                               String pluginOrder)
861      {
862        // If the provided plugin order string is null, empty, or contains only a
863        // wildcard, then simply add the new plugin to the end of the list.
864        // Otherwise, parse the order string and figure out where to put the
865        // provided plugin.
866        if ((pluginOrder == null) ||
867            ((pluginOrder = pluginOrder.trim()).length() == 0) ||
868            pluginOrder.equals("*"))
869        {
870          DirectoryServerPlugin[] newPlugins =
871               new DirectoryServerPlugin[pluginArray.length+1];
872          System.arraycopy(pluginArray, 0, newPlugins, 0, pluginArray.length);
873          newPlugins[pluginArray.length] = plugin;
874    
875          return newPlugins;
876        }
877        else
878        {
879          // Parse the plugin order into initial and final plugin names.
880          boolean starFound = false;
881          LinkedHashSet<String> initialPluginNames = new LinkedHashSet<String>();
882          LinkedHashSet<String> finalPluginNames   = new LinkedHashSet<String>();
883    
884          StringTokenizer tokenizer = new StringTokenizer(pluginOrder, ",");
885          while (tokenizer.hasMoreTokens())
886          {
887            String token = tokenizer.nextToken().trim();
888            if (token.length() == 0)
889            {
890              // Only log the warning once per plugin type.  The plugin array will
891              // be empty the first time through, so we can use that to make the
892              // determination.
893              if (pluginArray.length == 0)
894              {
895                Message message = WARN_CONFIG_PLUGIN_EMPTY_ELEMENT_IN_ORDER.get(
896                    pluginType.getName());
897                logError(message);
898              }
899            }
900            else if (token.equals("*"))
901            {
902              if (starFound)
903              {
904                // Only log the warning once per plugin type.  The plugin array will
905                // be empty the first time through, so we can use that to make the
906                // determination.
907                if (pluginArray.length == 0)
908                {
909                  Message message = WARN_CONFIG_PLUGIN_MULTIPLE_WILDCARDS_IN_ORDER.
910                      get(pluginType.getName());
911                  logError(message);
912                }
913              }
914              else
915              {
916                starFound = true;
917              }
918            }
919            else
920            {
921              String lowerName = toLowerCase(token);
922              if (starFound)
923              {
924                if (initialPluginNames.contains(lowerName) ||
925                    finalPluginNames.contains(lowerName))
926                {
927                  // Only log the warning once per plugin type.  The plugin array
928                  // will be empty the first time through, so we can use that to
929                  // make the determination.
930                  if (pluginArray.length == 0)
931                  {
932                    Message message = WARN_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES.get(
933                        pluginType.getName(), token);
934                    logError(message);
935                  }
936                }
937    
938                finalPluginNames.add(lowerName);
939              }
940              else
941              {
942                if (initialPluginNames.contains(lowerName))
943                {
944                  // Only log the warning once per plugin type.  The plugin array
945                  // will be empty the first time through, so we can use that to
946                  // make the determination.
947                  if (pluginArray.length == 0)
948                  {
949                    Message message = WARN_CONFIG_PLUGIN_LISTED_MULTIPLE_TIMES.get(
950                        pluginType.getName(), token);
951                    logError(message);
952                  }
953                }
954    
955                initialPluginNames.add(lowerName);
956              }
957            }
958          }
959    
960          if (! starFound)
961          {
962            // Only log the warning once per plugin type.  The plugin array will be
963            // empty the first time through, so we can use that to make the
964            // determination.
965            if (pluginArray.length == 0)
966            {
967              Message message =
968                  WARN_CONFIG_PLUGIN_ORDER_NO_WILDCARD.get(pluginType.getName());
969              logError(message);
970            }
971          }
972    
973    
974          // Parse the array of already registered plugins to sort them accordingly.
975          HashMap<String,DirectoryServerPlugin> initialPlugins =
976               new HashMap<String,DirectoryServerPlugin>(initialPluginNames.size());
977          HashMap<String,DirectoryServerPlugin> finalPlugins =
978               new HashMap<String,DirectoryServerPlugin>(finalPluginNames.size());
979          ArrayList<DirectoryServerPlugin> otherPlugins =
980               new ArrayList<DirectoryServerPlugin>();
981          for (DirectoryServerPlugin p : pluginArray)
982          {
983            DN dn = p.getPluginEntryDN();
984            String lowerName =
985                 toLowerCase(dn.getRDN().getAttributeValue(0).getStringValue());
986            if (initialPluginNames.contains(lowerName))
987            {
988              initialPlugins.put(lowerName, p);
989            }
990            else if (finalPluginNames.contains(lowerName))
991            {
992              finalPlugins.put(lowerName, p);
993            }
994            else
995            {
996              otherPlugins.add(p);
997            }
998          }
999    
1000    
1001          // Get the name of the provided plugin from its RDN value and put it in
1002          // the correct category.
1003          DN dn = plugin.getPluginEntryDN();
1004          String lowerName =
1005               toLowerCase(dn.getRDN().getAttributeValue(0).getStringValue());
1006          if (initialPluginNames.contains(lowerName))
1007          {
1008            initialPlugins.put(lowerName, plugin);
1009          }
1010          else if (finalPluginNames.contains(lowerName))
1011          {
1012            finalPlugins.put(lowerName, plugin);
1013          }
1014          else
1015          {
1016            otherPlugins.add(plugin);
1017          }
1018    
1019    
1020          // Compile a list of all the plugins in the correct order, convert it to
1021          // an array, and return it.
1022          ArrayList<DirectoryServerPlugin> newList =
1023               new ArrayList<DirectoryServerPlugin>(pluginArray.length+1);
1024          for (String name : initialPluginNames)
1025          {
1026            DirectoryServerPlugin p = initialPlugins.get(name);
1027            if (p != null)
1028            {
1029              newList.add(p);
1030            }
1031          }
1032    
1033          newList.addAll(otherPlugins);
1034    
1035          for (String name : finalPluginNames)
1036          {
1037            DirectoryServerPlugin p = finalPlugins.get(name);
1038            if (p != null)
1039            {
1040              newList.add(p);
1041            }
1042          }
1043    
1044          DirectoryServerPlugin[] newPlugins =
1045               new DirectoryServerPlugin[newList.size()];
1046          newList.toArray(newPlugins);
1047          return newPlugins;
1048        }
1049      }
1050    
1051    
1052    
1053      /**
1054       * Deregisters the plugin with the provided configuration entry DN.
1055       *
1056       * @param  configEntryDN  The DN of the configuration entry for the plugin to
1057       *                        deregister.
1058       */
1059      private void deregisterPlugin(DN configEntryDN)
1060      {
1061        pluginLock.lock();
1062    
1063        DirectoryServerPlugin<? extends PluginCfg> plugin;
1064        try
1065        {
1066          plugin = registeredPlugins.remove(configEntryDN);
1067          if (plugin == null)
1068          {
1069            return;
1070          }
1071    
1072          for (PluginType t : plugin.getPluginTypes())
1073          {
1074            switch (t)
1075            {
1076              case STARTUP:
1077                startupPlugins = removePlugin(startupPlugins, plugin);
1078                break;
1079              case SHUTDOWN:
1080                shutdownPlugins = removePlugin(shutdownPlugins, plugin);
1081                break;
1082              case POST_CONNECT:
1083                postConnectPlugins = removePlugin(postConnectPlugins, plugin);
1084                break;
1085              case POST_DISCONNECT:
1086                postDisconnectPlugins = removePlugin(postDisconnectPlugins, plugin);
1087                break;
1088              case LDIF_IMPORT:
1089                ldifImportPlugins = removePlugin(ldifImportPlugins, plugin);
1090                break;
1091              case LDIF_EXPORT:
1092                ldifExportPlugins = removePlugin(ldifExportPlugins, plugin);
1093                break;
1094              case PRE_PARSE_ABANDON:
1095                preParseAbandonPlugins = removePlugin(preParseAbandonPlugins,
1096                                                      plugin);
1097                break;
1098              case PRE_PARSE_ADD:
1099                preParseAddPlugins = removePlugin(preParseAddPlugins, plugin);
1100                break;
1101              case PRE_PARSE_BIND:
1102                preParseBindPlugins = removePlugin(preParseBindPlugins, plugin);
1103                break;
1104              case PRE_PARSE_COMPARE:
1105                preParseComparePlugins = removePlugin(preParseComparePlugins,
1106                                                      plugin);
1107                break;
1108              case PRE_PARSE_DELETE:
1109                preParseDeletePlugins = removePlugin(preParseDeletePlugins, plugin);
1110                break;
1111              case PRE_PARSE_EXTENDED:
1112                preParseExtendedPlugins = removePlugin(preParseExtendedPlugins,
1113                                                       plugin);
1114                break;
1115              case PRE_PARSE_MODIFY:
1116                preParseModifyPlugins = removePlugin(preParseModifyPlugins, plugin);
1117                break;
1118              case PRE_PARSE_MODIFY_DN:
1119                preParseModifyDNPlugins = removePlugin(preParseModifyDNPlugins,
1120                                                       plugin);
1121                break;
1122              case PRE_PARSE_SEARCH:
1123                preParseSearchPlugins = removePlugin(preParseSearchPlugins, plugin);
1124                break;
1125              case PRE_PARSE_UNBIND:
1126                preParseUnbindPlugins = removePlugin(preParseUnbindPlugins, plugin);
1127                break;
1128              case PRE_OPERATION_ADD:
1129                preOperationAddPlugins = removePlugin(preOperationAddPlugins,
1130                                                      plugin);
1131                break;
1132              case PRE_OPERATION_BIND:
1133                preOperationBindPlugins = removePlugin(preOperationBindPlugins,
1134                                                       plugin);
1135                break;
1136              case PRE_OPERATION_COMPARE:
1137                preOperationComparePlugins =
1138                     removePlugin(preOperationComparePlugins, plugin);
1139                break;
1140              case PRE_OPERATION_DELETE:
1141                preOperationDeletePlugins = removePlugin(preOperationDeletePlugins,
1142                                                         plugin);
1143                break;
1144              case PRE_OPERATION_EXTENDED:
1145                preOperationExtendedPlugins =
1146                     removePlugin(preOperationExtendedPlugins, plugin);
1147                break;
1148              case PRE_OPERATION_MODIFY:
1149                preOperationModifyPlugins = removePlugin(preOperationModifyPlugins,
1150                                                         plugin);
1151                break;
1152              case PRE_OPERATION_MODIFY_DN:
1153                preOperationModifyDNPlugins =
1154                     removePlugin(preOperationModifyDNPlugins, plugin);
1155                break;
1156              case PRE_OPERATION_SEARCH:
1157                preOperationSearchPlugins = removePlugin(preOperationSearchPlugins,
1158                                                         plugin);
1159                break;
1160              case POST_OPERATION_ABANDON:
1161                postOperationAbandonPlugins =
1162                     removePlugin(postOperationAbandonPlugins, plugin);
1163                break;
1164              case POST_OPERATION_ADD:
1165                postOperationAddPlugins = removePlugin(postOperationAddPlugins,
1166                                                       plugin);
1167                break;
1168              case POST_OPERATION_BIND:
1169                postOperationBindPlugins = removePlugin(postOperationBindPlugins,
1170                                                        plugin);
1171                break;
1172              case POST_OPERATION_COMPARE:
1173                postOperationComparePlugins =
1174                     removePlugin(postOperationComparePlugins, plugin);
1175                break;
1176              case POST_OPERATION_DELETE:
1177                postOperationDeletePlugins =
1178                     removePlugin(postOperationDeletePlugins, plugin);
1179                break;
1180              case POST_OPERATION_EXTENDED:
1181                postOperationExtendedPlugins =
1182                     removePlugin(postOperationExtendedPlugins, plugin);
1183                break;
1184              case POST_OPERATION_MODIFY:
1185                postOperationModifyPlugins =
1186                     removePlugin(postOperationModifyPlugins, plugin);
1187                break;
1188              case POST_OPERATION_MODIFY_DN:
1189                postOperationModifyDNPlugins =
1190                     removePlugin(postOperationModifyDNPlugins, plugin);
1191                break;
1192              case POST_OPERATION_SEARCH:
1193                postOperationSearchPlugins =
1194                     removePlugin(postOperationSearchPlugins, plugin);
1195                break;
1196              case POST_OPERATION_UNBIND:
1197                postOperationUnbindPlugins =
1198                     removePlugin(postOperationUnbindPlugins, plugin);
1199                break;
1200              case POST_RESPONSE_ADD:
1201                postResponseAddPlugins = removePlugin(postResponseAddPlugins,
1202                                                      plugin);
1203                break;
1204              case POST_RESPONSE_BIND:
1205                postResponseBindPlugins = removePlugin(postResponseBindPlugins,
1206                                                       plugin);
1207                break;
1208              case POST_RESPONSE_COMPARE:
1209                postResponseComparePlugins =
1210                     removePlugin(postResponseComparePlugins, plugin);
1211                break;
1212              case POST_RESPONSE_DELETE:
1213                postResponseDeletePlugins = removePlugin(postResponseDeletePlugins,
1214                                                         plugin);
1215                break;
1216              case POST_RESPONSE_EXTENDED:
1217                postResponseExtendedPlugins =
1218                     removePlugin(postResponseExtendedPlugins, plugin);
1219                break;
1220              case POST_RESPONSE_MODIFY:
1221                postResponseModifyPlugins = removePlugin(postResponseModifyPlugins,
1222                                                         plugin);
1223                break;
1224              case POST_RESPONSE_MODIFY_DN:
1225                postResponseModifyDNPlugins =
1226                     removePlugin(postResponseModifyDNPlugins, plugin);
1227                break;
1228              case POST_RESPONSE_SEARCH:
1229                postResponseSearchPlugins = removePlugin(postResponseSearchPlugins,
1230                                                         plugin);
1231                break;
1232              case POST_SYNCHRONIZATION_ADD:
1233                postSynchronizationAddPlugins =
1234                     removePlugin(postSynchronizationAddPlugins, plugin);
1235                break;
1236              case POST_SYNCHRONIZATION_DELETE:
1237                postSynchronizationDeletePlugins =
1238                     removePlugin(postSynchronizationDeletePlugins, plugin);
1239                break;
1240              case POST_SYNCHRONIZATION_MODIFY:
1241                postSynchronizationModifyPlugins =
1242                     removePlugin(postSynchronizationModifyPlugins, plugin);
1243                break;
1244              case POST_SYNCHRONIZATION_MODIFY_DN:
1245                postSynchronizationModifyDNPlugins =
1246                     removePlugin(postSynchronizationModifyDNPlugins, plugin);
1247                break;
1248              case SEARCH_RESULT_ENTRY:
1249                searchResultEntryPlugins = removePlugin(searchResultEntryPlugins,
1250                                                        plugin);
1251                break;
1252              case SEARCH_RESULT_REFERENCE:
1253                searchResultReferencePlugins =
1254                     removePlugin(searchResultReferencePlugins, plugin);
1255                break;
1256              case SUBORDINATE_MODIFY_DN:
1257                subordinateModifyDNPlugins =
1258                     removePlugin(subordinateModifyDNPlugins, plugin);
1259                break;
1260              case INTERMEDIATE_RESPONSE:
1261                intermediateResponsePlugins =
1262                     removePlugin(intermediateResponsePlugins, plugin);
1263                break;
1264              default:
1265            }
1266          }
1267        }
1268        finally
1269        {
1270          pluginLock.unlock();
1271        }
1272    
1273        plugin.finalizePlugin();
1274      }
1275    
1276    
1277    
1278      /**
1279       * Removes the provided plugin from the given array.  The provided array will
1280       * not itself be modified, but rather a new array will be created with one
1281       * fewer element (assuming that the specified plugin was found).
1282       *
1283       * @param  pluginArray  The array containing the existing set of plugins.
1284       * @param  plugin       The plugin to be removed from the array.
1285       *
1286       * @return  The new array containing the new set of plugins.
1287       */
1288      private DirectoryServerPlugin[]
1289                   removePlugin(DirectoryServerPlugin[] pluginArray,
1290                                DirectoryServerPlugin plugin)
1291      {
1292        int slot   = -1;
1293        int length = pluginArray.length;
1294        for (int i=0; i < length; i++)
1295        {
1296          if (pluginArray[i].getPluginEntryDN().equals(plugin.getPluginEntryDN()))
1297          {
1298            slot = i;
1299            break;
1300          }
1301        }
1302    
1303        if (slot < 0)
1304        {
1305          // The plugin wasn't found in the list, so return the same list.
1306          return pluginArray;
1307        }
1308    
1309    
1310        // If it was the only element in the array, then return an empty array.
1311        if (length == 0)
1312        {
1313          return new DirectoryServerPlugin[0];
1314        }
1315    
1316    
1317        // Create an array that's one element smaller and copy the remaining "good"
1318        // elements into it.
1319        DirectoryServerPlugin[] newPlugins = new DirectoryServerPlugin[length-1];
1320        if (slot > 0)
1321        {
1322          System.arraycopy(pluginArray, 0, newPlugins, 0, slot);
1323        }
1324    
1325        if (slot < (length-1))
1326        {
1327          System.arraycopy(pluginArray, slot+1, newPlugins, slot, (length-slot-1));
1328        }
1329    
1330        return newPlugins;
1331      }
1332    
1333    
1334    
1335      /**
1336       * Invokes the set of startup plugins that have been registered with the
1337       * Directory Server.
1338       *
1339       * @return  The result of processing the startup plugins.
1340       */
1341      public PluginResult.Startup invokeStartupPlugins()
1342      {
1343        PluginResult.Startup result = null;
1344    
1345        for (DirectoryServerPlugin p : startupPlugins)
1346        {
1347          try
1348          {
1349            result = p.doStartup();
1350          }
1351          catch (Exception e)
1352          {
1353            if (debugEnabled())
1354            {
1355              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1356            }
1357    
1358            Message message = ERR_PLUGIN_STARTUP_PLUGIN_EXCEPTION.get(
1359                    String.valueOf(p.getPluginEntryDN()),
1360                    stackTraceToSingleLineString(e));
1361    
1362            return PluginResult.Startup.stopStartup(message);
1363          }
1364    
1365          if (result == null)
1366          {
1367            Message message = ERR_PLUGIN_STARTUP_PLUGIN_RETURNED_NULL.get(
1368                String.valueOf(p.getPluginEntryDN()));
1369            logError(message);
1370            return PluginResult.Startup.stopStartup(message);
1371          }
1372          else if (! result.continueProcessing())
1373          {
1374            Message message = ERR_PLUGIN_STARTUP_PLUGIN_FAIL_ABORT.
1375                get(String.valueOf(p.getPluginEntryDN()),
1376                    result.getErrorMessage(),
1377                    result.getErrorMessage().getDescriptor().getId());
1378            logError(message);
1379            return result;
1380          }
1381        }
1382    
1383        if (result == null)
1384        {
1385          // This should only happen if there were no startup plugins registered,
1386          // which is fine.
1387          result = PluginResult.Startup.continueStartup();
1388        }
1389    
1390        return result;
1391      }
1392    
1393    
1394    
1395      /**
1396       * Invokes the set of shutdown plugins that have been configured in the
1397       * Directory Server.
1398       *
1399       * @param  reason  The human-readable reason for the shutdown.
1400       */
1401      public void invokeShutdownPlugins(Message reason)
1402      {
1403        for (DirectoryServerPlugin p : shutdownPlugins)
1404        {
1405          try
1406          {
1407            p.doShutdown(reason);
1408          }
1409          catch (Exception e)
1410          {
1411            if (debugEnabled())
1412            {
1413              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1414            }
1415    
1416            Message message = ERR_PLUGIN_SHUTDOWN_PLUGIN_EXCEPTION.
1417                get(String.valueOf(p.getPluginEntryDN()),
1418                    stackTraceToSingleLineString(e));
1419            logError(message);
1420          }
1421        }
1422      }
1423    
1424    
1425    
1426      /**
1427       * Invokes the set of post-connect plugins that have been configured in the
1428       * Directory Server.
1429       *
1430       * @param  clientConnection  The client connection that has been established.
1431       *
1432       * @return  The result of processing the post-connect plugins.
1433       */
1434      public PluginResult.PostConnect invokePostConnectPlugins(ClientConnection
1435                                                               clientConnection)
1436      {
1437        PluginResult.PostConnect result = null;
1438    
1439        for (DirectoryServerPlugin p : postConnectPlugins)
1440        {
1441          try
1442          {
1443            result = p.doPostConnect(clientConnection);
1444          }
1445          catch (Exception e)
1446          {
1447            if (debugEnabled())
1448            {
1449              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1450            }
1451    
1452            Message message = ERR_PLUGIN_POST_CONNECT_PLUGIN_EXCEPTION.
1453                get(String.valueOf(p.getPluginEntryDN()),
1454                    clientConnection.getConnectionID(),
1455                    clientConnection.getClientAddress(),
1456                    stackTraceToSingleLineString(e));
1457            logError(message);
1458    
1459            return PluginResult.PostConnect.disconnectClient(
1460                DisconnectReason.SERVER_ERROR, true, message);
1461          }
1462    
1463    
1464          if (result == null)
1465          {
1466            Message message = ERR_PLUGIN_POST_CONNECT_PLUGIN_RETURNED_NULL.
1467                get(String.valueOf(p.getPluginEntryDN()),
1468                    clientConnection.getConnectionID(),
1469                    clientConnection.getClientAddress());
1470            logError(message);
1471    
1472            return PluginResult.PostConnect.disconnectClient(
1473                DisconnectReason.SERVER_ERROR, true, message);
1474          }
1475          else if (!result.continuePluginProcessing())
1476          {
1477            return result;
1478          }
1479        }
1480    
1481        if (result == null)
1482        {
1483          // This should only happen if there were no post-connect plugins
1484          // registered, which is fine.
1485          result = PluginResult.PostConnect.continueConnectProcessing();
1486        }
1487    
1488        return result;
1489      }
1490    
1491    
1492    
1493      /**
1494       * Invokes the set of post-disconnect plugins that have been configured in the
1495       * Directory Server.
1496       *
1497       * @param  clientConnection  The client connection that has been closed.
1498       * @param  disconnectReason  The general reason that the connection was
1499       *                           closed.
1500       * @param  message           A human-readable message that may provide
1501       *                           additional information about the closure.
1502       *
1503       * @return  The result of processing the post-connect plugins.
1504       */
1505      public PluginResult.PostDisconnect invokePostDisconnectPlugins(
1506                                            ClientConnection clientConnection,
1507                                            DisconnectReason disconnectReason,
1508                                            Message message)
1509      {
1510        PluginResult.PostDisconnect result = null;
1511    
1512        for (DirectoryServerPlugin p : postDisconnectPlugins)
1513        {
1514          try
1515          {
1516            result = p.doPostDisconnect(clientConnection, disconnectReason,
1517                    message);
1518          }
1519          catch (Exception e)
1520          {
1521            if (debugEnabled())
1522            {
1523              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1524            }
1525    
1526            Message msg = ERR_PLUGIN_POST_DISCONNECT_PLUGIN_EXCEPTION.
1527                get(String.valueOf(p.getPluginEntryDN()),
1528                    clientConnection.getConnectionID(),
1529                    clientConnection.getClientAddress(),
1530                    stackTraceToSingleLineString(e));
1531            logError(msg);
1532          }
1533    
1534    
1535          if (result == null)
1536          {
1537            Message msg = ERR_PLUGIN_POST_DISCONNECT_PLUGIN_RETURNED_NULL.
1538                get(String.valueOf(p.getPluginEntryDN()),
1539                    clientConnection.getConnectionID(),
1540                    clientConnection.getClientAddress());
1541            logError(msg);
1542          }
1543          else if (! result.continuePluginProcessing())
1544          {
1545            return result;
1546          }
1547        }
1548    
1549        if (result == null)
1550        {
1551          // This should only happen if there were no post-disconnect plugins
1552          // registered, which is fine.
1553          result = PluginResult.PostDisconnect.continueDisconnectProcessing();
1554        }
1555    
1556        return result;
1557      }
1558    
1559    
1560    
1561      /**
1562       * Invokes the set of LDIF import plugins that have been configured in the
1563       * Directory Server.
1564       *
1565       * @param  importConfig  The LDIF import configuration used to read the
1566       *                       associated entry.
1567       * @param  entry         The entry that has been read from LDIF.
1568       *
1569       * @return  The result of processing the LDIF import plugins.
1570       */
1571      public PluginResult.ImportLDIF invokeLDIFImportPlugins(
1572          LDIFImportConfig importConfig, Entry entry)
1573      {
1574        PluginResult.ImportLDIF result = null;
1575    
1576        for (DirectoryServerPlugin p : ldifImportPlugins)
1577        {
1578          try
1579          {
1580            result = p.doLDIFImport(importConfig, entry);
1581          }
1582          catch (Exception e)
1583          {
1584            if (debugEnabled())
1585            {
1586              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1587            }
1588    
1589            Message message = ERR_PLUGIN_LDIF_IMPORT_PLUGIN_EXCEPTION.
1590                get(String.valueOf(p.getPluginEntryDN()),
1591                    String.valueOf(entry.getDN()), stackTraceToSingleLineString(e));
1592            logError(message);
1593    
1594            return PluginResult.ImportLDIF.stopEntryProcessing(message);
1595          }
1596    
1597          if (result == null)
1598          {
1599            Message message = ERR_PLUGIN_LDIF_IMPORT_PLUGIN_RETURNED_NULL.
1600                get(String.valueOf(p.getPluginEntryDN()),
1601                    String.valueOf(entry.getDN()));
1602            logError(message);
1603    
1604            return PluginResult.ImportLDIF.stopEntryProcessing(message);
1605          }
1606          else if (! result.continuePluginProcessing())
1607          {
1608            return result;
1609          }
1610        }
1611    
1612        if (result == null)
1613        {
1614          // This should only happen if there were no LDIF import plugins
1615          // registered, which is fine.
1616          result = PluginResult.ImportLDIF.continueEntryProcessing();
1617        }
1618    
1619        return result;
1620      }
1621    
1622    
1623    
1624      /**
1625       * Invokes the set of LDIF export plugins that have been configured in the
1626       * Directory Server.
1627       *
1628       * @param  exportConfig  The LDIF export configuration used to read the
1629       *                       associated entry.
1630       * @param  entry         The entry that has been read from LDIF.
1631       *
1632       * @return  The result of processing the LDIF export plugins.
1633       */
1634      public PluginResult.ImportLDIF invokeLDIFExportPlugins(
1635          LDIFExportConfig exportConfig, Entry entry)
1636      {
1637        PluginResult.ImportLDIF result = null;
1638    
1639        for (DirectoryServerPlugin p : ldifExportPlugins)
1640        {
1641          try
1642          {
1643            result = p.doLDIFExport(exportConfig, entry);
1644          }
1645          catch (Exception e)
1646          {
1647            if (debugEnabled())
1648            {
1649              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1650            }
1651    
1652            Message message = ERR_PLUGIN_LDIF_EXPORT_PLUGIN_EXCEPTION.
1653                get(String.valueOf(p.getPluginEntryDN()),
1654                    String.valueOf(entry.getDN()), stackTraceToSingleLineString(e));
1655            logError(message);
1656    
1657            return PluginResult.ImportLDIF.stopEntryProcessing(message);
1658          }
1659    
1660          if (result == null)
1661          {
1662            Message message = ERR_PLUGIN_LDIF_EXPORT_PLUGIN_RETURNED_NULL.
1663                get(String.valueOf(p.getPluginEntryDN()),
1664                    String.valueOf(entry.getDN()));
1665            logError(message);
1666    
1667            return PluginResult.ImportLDIF.stopEntryProcessing(message);
1668          }
1669          else if (! result.continuePluginProcessing())
1670          {
1671            return result;
1672          }
1673        }
1674    
1675        if (result == null)
1676        {
1677          // This should only happen if there were no LDIF export plugins
1678          // registered, which is fine.
1679          result = PluginResult.ImportLDIF.continueEntryProcessing();
1680        }
1681    
1682        return result;
1683      }
1684    
1685    
1686    
1687      /**
1688       * Invokes the set of pre-parse abandon plugins that have been configured in
1689       * the Directory Server.
1690       *
1691       * @param  abandonOperation  The abandon operation for which to invoke the
1692       *                           pre-parse plugins.
1693       *
1694       * @return  The result of processing the pre-parse abandon plugins.
1695       */
1696      public PluginResult.PreParse invokePreParseAbandonPlugins(
1697                                       PreParseAbandonOperation abandonOperation)
1698      {
1699        PluginResult.PreParse result = null;
1700    
1701        for (DirectoryServerPlugin p : preParseAbandonPlugins)
1702        {
1703          if (abandonOperation.isInternalOperation() &&
1704              (! p.invokeForInternalOperations()))
1705          {
1706            continue;
1707          }
1708    
1709          try
1710          {
1711            result = p.doPreParse(abandonOperation);
1712          }
1713          catch (Exception e)
1714          {
1715            if (debugEnabled())
1716            {
1717              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1718            }
1719    
1720            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
1721                get(abandonOperation.getOperationType().getOperationName(),
1722                    String.valueOf(p.getPluginEntryDN()),
1723                    abandonOperation.getConnectionID(),
1724                    abandonOperation.getOperationID(),
1725                    stackTraceToSingleLineString(e));
1726            logError(message);
1727    
1728            return PluginResult.PreParse.stopProcessing(
1729                DirectoryServer.getServerErrorResultCode(), message);
1730          }
1731    
1732          if (result == null)
1733          {
1734            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
1735                get(abandonOperation.getOperationType().getOperationName(),
1736                    String.valueOf(p.getPluginEntryDN()),
1737                    abandonOperation.getConnectionID(),
1738                    String.valueOf(abandonOperation.getOperationID()));
1739            logError(message);
1740    
1741            return PluginResult.PreParse.stopProcessing(
1742                DirectoryServer.getServerErrorResultCode(), message);
1743          }
1744          else if (!result.continuePluginProcessing())
1745          {
1746            return result;
1747          }
1748        }
1749    
1750        if (result == null)
1751        {
1752          // This should only happen if there were no pre-parse abandon plugins
1753          // registered, which is fine.
1754          result = PluginResult.PreParse.continueOperationProcessing();
1755        }
1756    
1757        return result;
1758      }
1759    
1760    
1761    
1762      /**
1763       * Invokes the set of pre-parse add plugins that have been configured in the
1764       * Directory Server.
1765       *
1766       * @param  addOperation  The add operation for which to invoke the pre-parse
1767       *                       plugins.
1768       *
1769       * @return  The result of processing the pre-parse add plugins.
1770       *
1771       * @throws CanceledOperationException if the operation should be canceled.
1772       */
1773      public PluginResult.PreParse invokePreParseAddPlugins(
1774          PreParseAddOperation addOperation)
1775          throws CanceledOperationException {
1776        PluginResult.PreParse result = null;
1777    
1778        for (DirectoryServerPlugin p : preParseAddPlugins)
1779        {
1780          if (addOperation.isInternalOperation() &&
1781              (! p.invokeForInternalOperations()))
1782          {
1783            continue;
1784          }
1785    
1786          try
1787          {
1788            result = p.doPreParse(addOperation);
1789          }
1790          catch (CanceledOperationException coe)
1791          {
1792            throw coe;
1793          }
1794          catch (Exception e)
1795          {
1796            if (debugEnabled())
1797            {
1798              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1799            }
1800    
1801            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
1802                get(addOperation.getOperationType().getOperationName(),
1803                    String.valueOf(p.getPluginEntryDN()),
1804                    addOperation.getConnectionID(), addOperation.getOperationID(),
1805                    stackTraceToSingleLineString(e));
1806            logError(message);
1807    
1808            return PluginResult.PreParse.stopProcessing(
1809                DirectoryServer.getServerErrorResultCode(), message);
1810          }
1811    
1812          if (result == null)
1813          {
1814            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
1815                get(addOperation.getOperationType().getOperationName(),
1816                    String.valueOf(p.getPluginEntryDN()),
1817                    addOperation.getConnectionID(),
1818                    String.valueOf(addOperation.getOperationID()));
1819            logError(message);
1820    
1821            return PluginResult.PreParse.stopProcessing(
1822                DirectoryServer.getServerErrorResultCode(), message);
1823          }
1824          else if (!result.continuePluginProcessing())
1825          {
1826            return result;
1827          }
1828        }
1829    
1830        if (result == null)
1831        {
1832          // This should only happen if there were no pre-parse add plugins
1833          // registered, which is fine.
1834          result = PluginResult.PreParse.continueOperationProcessing();
1835        }
1836    
1837        return result;
1838      }
1839    
1840    
1841    
1842      /**
1843       * Invokes the set of pre-parse bind plugins that have been configured in
1844       * the Directory Server.
1845       *
1846       * @param  bindOperation  The bind operation for which to invoke the pre-parse
1847       *                        plugins.
1848       *
1849       * @return  The result of processing the pre-parse bind plugins.
1850       */
1851      public PluginResult.PreParse invokePreParseBindPlugins(
1852                                       PreParseBindOperation bindOperation)
1853      {
1854        PluginResult.PreParse result = null;
1855    
1856        for (DirectoryServerPlugin p : preParseBindPlugins)
1857        {
1858          if (bindOperation.isInternalOperation() &&
1859              (! p.invokeForInternalOperations()))
1860          {
1861            continue;
1862          }
1863    
1864          try
1865          {
1866            result = p.doPreParse(bindOperation);
1867          }
1868          catch (Exception e)
1869          {
1870            if (debugEnabled())
1871            {
1872              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1873            }
1874    
1875            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
1876                get(bindOperation.getOperationType().getOperationName(),
1877                    String.valueOf(p.getPluginEntryDN()),
1878                    bindOperation.getConnectionID(), bindOperation.getOperationID(),
1879                    stackTraceToSingleLineString(e));
1880            logError(message);
1881    
1882            return PluginResult.PreParse.stopProcessing(
1883                DirectoryServer.getServerErrorResultCode(), message);
1884          }
1885    
1886          if (result == null)
1887          {
1888            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
1889                get(bindOperation.getOperationType().getOperationName(),
1890                    String.valueOf(p.getPluginEntryDN()),
1891                    bindOperation.getConnectionID(),
1892                    String.valueOf(bindOperation.getOperationID()));
1893            logError(message);
1894    
1895            return PluginResult.PreParse.stopProcessing(
1896                DirectoryServer.getServerErrorResultCode(), message);
1897          }
1898          else if (!result.continuePluginProcessing())
1899          {
1900            return result;
1901          }
1902        }
1903    
1904        if (result == null)
1905        {
1906          // This should only happen if there were no pre-parse bind plugins
1907          // registered, which is fine.
1908          result = PluginResult.PreParse.continueOperationProcessing();
1909        }
1910    
1911        return result;
1912      }
1913    
1914    
1915    
1916      /**
1917       * Invokes the set of pre-parse compare plugins that have been configured in
1918       * the Directory Server.
1919       *
1920       * @param  compareOperation  The compare operation for which to invoke the
1921       *                           pre-parse plugins.
1922       *
1923       * @return  The result of processing the pre-parse compare plugins.
1924       *
1925       * @throws CanceledOperationException if the operation should be canceled.
1926       */
1927      public PluginResult.PreParse invokePreParseComparePlugins(
1928          PreParseCompareOperation compareOperation)
1929          throws CanceledOperationException {
1930        PluginResult.PreParse result = null;
1931    
1932        for (DirectoryServerPlugin p : preParseComparePlugins)
1933        {
1934          if (compareOperation.isInternalOperation() &&
1935              (! p.invokeForInternalOperations()))
1936          {
1937            continue;
1938          }
1939    
1940          try
1941          {
1942            result = p.doPreParse(compareOperation);
1943          }
1944          catch (CanceledOperationException coe)
1945          {
1946            throw coe;
1947          }
1948          catch (Exception e)
1949          {
1950            if (debugEnabled())
1951            {
1952              TRACER.debugCaught(DebugLogLevel.ERROR, e);
1953            }
1954    
1955            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
1956                get(compareOperation.getOperationType().getOperationName(),
1957                    String.valueOf(p.getPluginEntryDN()),
1958                    compareOperation.getConnectionID(),
1959                    compareOperation.getOperationID(),
1960                    stackTraceToSingleLineString(e));
1961            logError(message);
1962    
1963            return PluginResult.PreParse.stopProcessing(
1964                DirectoryServer.getServerErrorResultCode(), message);
1965          }
1966    
1967          if (result == null)
1968          {
1969            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
1970                get(compareOperation.getOperationType().getOperationName(),
1971                    String.valueOf(p.getPluginEntryDN()),
1972                    compareOperation.getConnectionID(),
1973                    String.valueOf(compareOperation.getOperationID()));
1974            logError(message);
1975    
1976            return PluginResult.PreParse.stopProcessing(
1977                DirectoryServer.getServerErrorResultCode(), message);
1978          }
1979          else if (!result.continuePluginProcessing())
1980          {
1981            return result;
1982          }
1983        }
1984    
1985        if (result == null)
1986        {
1987          // This should only happen if there were no pre-parse compare plugins
1988          // registered, which is fine.
1989          result = PluginResult.PreParse.continueOperationProcessing();
1990        }
1991    
1992        return result;
1993      }
1994    
1995    
1996    
1997      /**
1998       * Invokes the set of pre-parse delete plugins that have been configured in
1999       * the Directory Server.
2000       *
2001       * @param  deleteOperation  The delete operation for which to invoke the
2002       *                          pre-parse plugins.
2003       *
2004       * @return  The result of processing the pre-parse delete plugins.
2005       *
2006       * @throws CanceledOperationException if the operation should be canceled.
2007       */
2008      public PluginResult.PreParse invokePreParseDeletePlugins(
2009                                  PreParseDeleteOperation deleteOperation)
2010          throws CanceledOperationException {
2011        PluginResult.PreParse result = null;
2012    
2013        for (DirectoryServerPlugin p : preParseDeletePlugins)
2014        {
2015          if (deleteOperation.isInternalOperation() &&
2016              (! p.invokeForInternalOperations()))
2017          {
2018            continue;
2019          }
2020    
2021          try
2022          {
2023            result = p.doPreParse(deleteOperation);
2024          }
2025          catch (CanceledOperationException coe)
2026          {
2027            throw coe;
2028          }
2029          catch (Exception e)
2030          {
2031            if (debugEnabled())
2032            {
2033              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2034            }
2035    
2036            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2037                get(deleteOperation.getOperationType().getOperationName(),
2038                    String.valueOf(p.getPluginEntryDN()),
2039                    deleteOperation.getConnectionID(),
2040                    deleteOperation.getOperationID(),
2041                    stackTraceToSingleLineString(e));
2042            logError(message);
2043    
2044            return PluginResult.PreParse.stopProcessing(
2045                DirectoryServer.getServerErrorResultCode(), message);
2046          }
2047    
2048          if (result == null)
2049          {
2050            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2051                get(deleteOperation.getOperationType().getOperationName(),
2052                    String.valueOf(p.getPluginEntryDN()),
2053                    deleteOperation.getConnectionID(),
2054                    String.valueOf(deleteOperation.getOperationID()));
2055            logError(message);
2056    
2057            return PluginResult.PreParse.stopProcessing(
2058                DirectoryServer.getServerErrorResultCode(), message);
2059          }
2060          else if (!result.continuePluginProcessing())
2061          {
2062            return result;
2063          }
2064        }
2065    
2066        if (result == null)
2067        {
2068          // This should only happen if there were no pre-parse delete plugins
2069          // registered, which is fine.
2070          result = PluginResult.PreParse.continueOperationProcessing();
2071        }
2072    
2073        return result;
2074      }
2075    
2076    
2077    
2078      /**
2079       * Invokes the set of pre-parse extended plugins that have been configured in
2080       * the Directory Server.
2081       *
2082       * @param  extendedOperation  The extended operation for which to invoke the
2083       *                            pre-parse plugins.
2084       *
2085       * @return  The result of processing the pre-parse extended plugins.
2086       *
2087       * @throws CanceledOperationException if the operation should be canceled.
2088       */
2089      public PluginResult.PreParse invokePreParseExtendedPlugins(
2090                                       PreParseExtendedOperation extendedOperation)
2091          throws CanceledOperationException {
2092        PluginResult.PreParse result = null;
2093    
2094        for (DirectoryServerPlugin p : preParseExtendedPlugins)
2095        {
2096          if (extendedOperation.isInternalOperation() &&
2097              (! p.invokeForInternalOperations()))
2098          {
2099            continue;
2100          }
2101    
2102          try
2103          {
2104            result = p.doPreParse(extendedOperation);
2105          }
2106          catch (CanceledOperationException coe)
2107          {
2108            throw coe;
2109          }
2110          catch (Exception e)
2111          {
2112            if (debugEnabled())
2113            {
2114              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2115            }
2116    
2117            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2118                get(extendedOperation.getOperationType().getOperationName(),
2119                    String.valueOf(p.getPluginEntryDN()),
2120                    extendedOperation.getConnectionID(),
2121                    extendedOperation.getOperationID(),
2122                    stackTraceToSingleLineString(e));
2123            logError(message);
2124    
2125            return PluginResult.PreParse.stopProcessing(
2126                DirectoryServer.getServerErrorResultCode(), message);
2127          }
2128    
2129          if (result == null)
2130          {
2131            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2132                get(extendedOperation.getOperationType().getOperationName(),
2133                    String.valueOf(p.getPluginEntryDN()),
2134                    extendedOperation.getConnectionID(),
2135                    String.valueOf(extendedOperation.getOperationID()));
2136            logError(message);
2137    
2138            return PluginResult.PreParse.stopProcessing(
2139                DirectoryServer.getServerErrorResultCode(), message);
2140          }
2141          else if (!result.continuePluginProcessing())
2142          {
2143            return result;
2144          }
2145        }
2146    
2147        if (result == null)
2148        {
2149          // This should only happen if there were no pre-parse extended plugins
2150          // registered, which is fine.
2151          result = PluginResult.PreParse.continueOperationProcessing();
2152        }
2153    
2154        return result;
2155      }
2156    
2157    
2158    
2159      /**
2160       * Invokes the set of pre-parse modify plugins that have been configured in
2161       * the Directory Server.
2162       *
2163       * @param  modifyOperation  The modify operation for which to invoke the
2164       *                          pre-parse plugins.
2165       *
2166       * @return  The result of processing the pre-parse modify plugins.
2167       *
2168       * @throws CanceledOperationException if the operation should be canceled.
2169       */
2170      public PluginResult.PreParse invokePreParseModifyPlugins(
2171                                       PreParseModifyOperation modifyOperation)
2172          throws CanceledOperationException {
2173        PluginResult.PreParse result = null;
2174    
2175        for (DirectoryServerPlugin p : preParseModifyPlugins)
2176        {
2177          if (modifyOperation.isInternalOperation() &&
2178              (! p.invokeForInternalOperations()))
2179          {
2180            continue;
2181          }
2182    
2183          try
2184          {
2185            result = p.doPreParse(modifyOperation);
2186          }
2187          catch (CanceledOperationException coe)
2188          {
2189            throw coe;
2190          }
2191          catch (Exception e)
2192          {
2193            if (debugEnabled())
2194            {
2195              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2196            }
2197    
2198            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2199                get(modifyOperation.getOperationType().getOperationName(),
2200                    String.valueOf(p.getPluginEntryDN()),
2201                    modifyOperation.getConnectionID(),
2202                    modifyOperation.getOperationID(),
2203                    stackTraceToSingleLineString(e));
2204            logError(message);
2205    
2206            return PluginResult.PreParse.stopProcessing(
2207                DirectoryServer.getServerErrorResultCode(), message);
2208          }
2209    
2210          if (result == null)
2211          {
2212            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2213                get(modifyOperation.getOperationType().getOperationName(),
2214                    String.valueOf(p.getPluginEntryDN()),
2215                    modifyOperation.getConnectionID(),
2216                    String.valueOf(modifyOperation.getOperationID()));
2217            logError(message);
2218    
2219            return PluginResult.PreParse.stopProcessing(
2220                DirectoryServer.getServerErrorResultCode(), message);
2221          }
2222          else if (!result.continuePluginProcessing())
2223          {
2224            return result;
2225          }
2226        }
2227    
2228        if (result == null)
2229        {
2230          // This should only happen if there were no pre-parse modify plugins
2231          // registered, which is fine.
2232          result = PluginResult.PreParse.continueOperationProcessing();
2233        }
2234    
2235        return result;
2236      }
2237    
2238    
2239    
2240      /**
2241       * Invokes the set of pre-parse modify DN plugins that have been configured in
2242       * the Directory Server.
2243       *
2244       * @param  modifyDNOperation  The modify DN operation for which to invoke the
2245       *                            pre-parse plugins.
2246       *
2247       * @return  The result of processing the pre-parse modify DN plugins.
2248       *
2249       * @throws CanceledOperationException if the operation should be canceled.
2250       */
2251      public PluginResult.PreParse invokePreParseModifyDNPlugins(
2252                                       PreParseModifyDNOperation modifyDNOperation)
2253          throws CanceledOperationException {
2254        PluginResult.PreParse result = null;
2255    
2256        for (DirectoryServerPlugin p : preParseModifyDNPlugins)
2257        {
2258          if (modifyDNOperation.isInternalOperation() &&
2259              (! p.invokeForInternalOperations()))
2260          {
2261            continue;
2262          }
2263    
2264          try
2265          {
2266            result = p.doPreParse(modifyDNOperation);
2267          }
2268          catch (CanceledOperationException coe)
2269          {
2270            throw coe;
2271          }
2272          catch (Exception e)
2273          {
2274            if (debugEnabled())
2275            {
2276              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2277            }
2278    
2279            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2280                get(modifyDNOperation.getOperationType().getOperationName(),
2281                    String.valueOf(p.getPluginEntryDN()),
2282                    modifyDNOperation.getConnectionID(),
2283                    modifyDNOperation.getOperationID(),
2284                    stackTraceToSingleLineString(e));
2285            logError(message);
2286    
2287            return PluginResult.PreParse.stopProcessing(
2288                DirectoryServer.getServerErrorResultCode(), message);
2289          }
2290    
2291          if (result == null)
2292          {
2293            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2294                get(modifyDNOperation.getOperationType().getOperationName(),
2295                    String.valueOf(p.getPluginEntryDN()),
2296                    modifyDNOperation.getConnectionID(),
2297                    String.valueOf(modifyDNOperation.getOperationID()));
2298            logError(message);
2299    
2300            return PluginResult.PreParse.stopProcessing(
2301                DirectoryServer.getServerErrorResultCode(), message);
2302          }
2303          else if (!result.continuePluginProcessing())
2304          {
2305            return result;
2306          }
2307        }
2308    
2309        if (result == null)
2310        {
2311          // This should only happen if there were no pre-parse modify DN plugins
2312          // registered, which is fine.
2313          result = PluginResult.PreParse.continueOperationProcessing();
2314        }
2315    
2316        return result;
2317      }
2318    
2319    
2320    
2321      /**
2322       * Invokes the set of pre-parse search plugins that have been configured in
2323       * the Directory Server.
2324       *
2325       * @param  searchOperation  The search operation for which to invoke the
2326       *                          pre-parse plugins.
2327       *
2328       * @return  The result of processing the pre-parse search plugins.
2329       *
2330       * @throws CanceledOperationException if the operation should be canceled.
2331       */
2332      public PluginResult.PreParse invokePreParseSearchPlugins(
2333                                       PreParseSearchOperation searchOperation)
2334          throws CanceledOperationException {
2335        PluginResult.PreParse result = null;
2336    
2337        for (DirectoryServerPlugin p : preParseSearchPlugins)
2338        {
2339          if (searchOperation.isInternalOperation() &&
2340              (! p.invokeForInternalOperations()))
2341          {
2342            continue;
2343          }
2344    
2345          try
2346          {
2347            result = p.doPreParse(searchOperation);
2348          }
2349          catch (CanceledOperationException coe)
2350          {
2351            throw coe;
2352          }
2353          catch (Exception e)
2354          {
2355            if (debugEnabled())
2356            {
2357              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2358            }
2359    
2360            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2361                get(searchOperation.getOperationType().getOperationName(),
2362                    String.valueOf(p.getPluginEntryDN()),
2363                    searchOperation.getConnectionID(),
2364                    searchOperation.getOperationID(),
2365                    stackTraceToSingleLineString(e));
2366            logError(message);
2367    
2368            return PluginResult.PreParse.stopProcessing(
2369                DirectoryServer.getServerErrorResultCode(), message);
2370          }
2371    
2372          if (result == null)
2373          {
2374            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2375                get(searchOperation.getOperationType().getOperationName(),
2376                    String.valueOf(p.getPluginEntryDN()),
2377                    searchOperation.getConnectionID(),
2378                    String.valueOf(searchOperation.getOperationID()));
2379            logError(message);
2380    
2381            return PluginResult.PreParse.stopProcessing(
2382                DirectoryServer.getServerErrorResultCode(), message);
2383          }
2384          else if (!result.continuePluginProcessing())
2385          {
2386            return result;
2387          }
2388        }
2389    
2390        if (result == null)
2391        {
2392          // This should only happen if there were no pre-parse search plugins
2393          // registered, which is fine.
2394          result = PluginResult.PreParse.continueOperationProcessing();
2395        }
2396    
2397        return result;
2398      }
2399    
2400    
2401    
2402      /**
2403       * Invokes the set of pre-parse unbind plugins that have been configured in
2404       * the Directory Server.
2405       *
2406       * @param  unbindOperation  The unbind operation for which to invoke the
2407       *                          pre-parse plugins.
2408       *
2409       * @return  The result of processing the pre-parse unbind plugins.
2410       */
2411      public PluginResult.PreParse invokePreParseUnbindPlugins(
2412                                       PreParseUnbindOperation unbindOperation)
2413      {
2414        PluginResult.PreParse result = null;
2415    
2416        for (DirectoryServerPlugin p : preParseUnbindPlugins)
2417        {
2418          if (unbindOperation.isInternalOperation() &&
2419              (! p.invokeForInternalOperations()))
2420          {
2421            continue;
2422          }
2423    
2424          try
2425          {
2426            result = p.doPreParse(unbindOperation);
2427          }
2428          catch (Exception e)
2429          {
2430            if (debugEnabled())
2431            {
2432              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2433            }
2434    
2435            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION.
2436                get(unbindOperation.getOperationType().getOperationName(),
2437                    String.valueOf(p.getPluginEntryDN()),
2438                    unbindOperation.getConnectionID(),
2439                    unbindOperation.getOperationID(),
2440                    stackTraceToSingleLineString(e));
2441            logError(message);
2442    
2443            return PluginResult.PreParse.stopProcessing(
2444                DirectoryServer.getServerErrorResultCode(), message);
2445          }
2446    
2447          if (result == null)
2448          {
2449            Message message = ERR_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL.
2450                get(unbindOperation.getOperationType().getOperationName(),
2451                    String.valueOf(p.getPluginEntryDN()),
2452                    unbindOperation.getConnectionID(),
2453                    String.valueOf(unbindOperation.getOperationID()));
2454            logError(message);
2455    
2456            return PluginResult.PreParse.stopProcessing(
2457                DirectoryServer.getServerErrorResultCode(), message);
2458          }
2459          else if (!result.continuePluginProcessing())
2460          {
2461            return result;
2462          }
2463        }
2464    
2465        if (result == null)
2466        {
2467          // This should only happen if there were no pre-parse unbind plugins
2468          // registered, which is fine.
2469          result = PluginResult.PreParse.continueOperationProcessing();
2470        }
2471    
2472        return result;
2473      }
2474    
2475    
2476    
2477      /**
2478       * Invokes the set of pre-operation add plugins that have been configured in
2479       * the Directory Server.
2480       *
2481       * @param  addOperation  The add operation for which to invoke the
2482       *                       pre-operation plugins.
2483       *
2484       * @return  The result of processing the pre-operation add plugins.
2485       *
2486       * @throws CanceledOperationException if the operation should be canceled.
2487       */
2488      public PluginResult.PreOperation invokePreOperationAddPlugins(
2489                                           PreOperationAddOperation addOperation)
2490          throws CanceledOperationException {
2491        PluginResult.PreOperation result = null;
2492    
2493        for (int i = 0; i < preOperationAddPlugins.length; i++)
2494        {
2495          DirectoryServerPlugin p = preOperationAddPlugins[i];
2496          if (addOperation.isInternalOperation() &&
2497              (! p.invokeForInternalOperations()))
2498          {
2499            continue;
2500          }
2501    
2502          try
2503          {
2504            result = p.doPreOperation(addOperation);
2505          }
2506          catch (CanceledOperationException coe)
2507          {
2508            throw coe;
2509          }
2510          catch (Exception e)
2511          {
2512            if (debugEnabled())
2513            {
2514              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2515            }
2516    
2517            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2518                get(addOperation.getOperationType().getOperationName(),
2519                    String.valueOf(p.getPluginEntryDN()),
2520                    addOperation.getConnectionID(), addOperation.getOperationID(),
2521                    stackTraceToSingleLineString(e));
2522            logError(message);
2523    
2524            registerSkippedPreOperationPlugins(i, preOperationAddPlugins,
2525                addOperation);
2526    
2527            return PluginResult.PreOperation.stopProcessing(
2528                DirectoryServer.getServerErrorResultCode(), message);
2529          }
2530    
2531          if (result == null)
2532          {
2533            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2534                get(addOperation.getOperationType().getOperationName(),
2535                    String.valueOf(p.getPluginEntryDN()),
2536                    addOperation.getConnectionID(), addOperation.getOperationID());
2537            logError(message);
2538    
2539            registerSkippedPreOperationPlugins(i, preOperationAddPlugins,
2540                addOperation);
2541    
2542            return PluginResult.PreOperation.stopProcessing(
2543                DirectoryServer.getServerErrorResultCode(), message);
2544          }
2545          else if (!result.continuePluginProcessing())
2546          {
2547            registerSkippedPreOperationPlugins(i, preOperationAddPlugins,
2548                addOperation);
2549            return result;
2550          }
2551        }
2552    
2553        if (result == null)
2554        {
2555          // This should only happen if there were no pre-operation add plugins
2556          // registered, which is fine.
2557          result = PluginResult.PreOperation.continueOperationProcessing();
2558        }
2559    
2560        return result;
2561      }
2562    
2563    
2564    
2565      /**
2566       * Invokes the set of pre-operation bind plugins that have been configured in
2567       * the Directory Server.
2568       *
2569       * @param  bindOperation  The bind operation for which to invoke the
2570       *                        pre-operation plugins.
2571       *
2572       * @return  The result of processing the pre-operation bind plugins.
2573       */
2574      public PluginResult.PreOperation invokePreOperationBindPlugins(
2575                                           PreOperationBindOperation bindOperation)
2576      {
2577        PluginResult.PreOperation result = null;
2578    
2579        for (int i = 0; i < preOperationBindPlugins.length; i++)
2580        {
2581          DirectoryServerPlugin p = preOperationBindPlugins[i];
2582          if (bindOperation.isInternalOperation() &&
2583              (! p.invokeForInternalOperations()))
2584          {
2585            continue;
2586          }
2587    
2588          try
2589          {
2590            result = p.doPreOperation(bindOperation);
2591          }
2592          catch (Exception e)
2593          {
2594            if (debugEnabled())
2595            {
2596              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2597            }
2598    
2599            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2600                get(bindOperation.getOperationType().getOperationName(),
2601                    String.valueOf(p.getPluginEntryDN()),
2602                    bindOperation.getConnectionID(), bindOperation.getOperationID(),
2603                    stackTraceToSingleLineString(e));
2604            logError(message);
2605    
2606            registerSkippedPreOperationPlugins(i, preOperationBindPlugins,
2607                bindOperation);
2608    
2609            return PluginResult.PreOperation.stopProcessing(
2610                DirectoryServer.getServerErrorResultCode(), message);
2611          }
2612    
2613          if (result == null)
2614          {
2615            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2616                get(bindOperation.getOperationType().getOperationName(),
2617                    String.valueOf(p.getPluginEntryDN()),
2618                    bindOperation.getConnectionID(),
2619                    bindOperation.getOperationID());
2620            logError(message);
2621    
2622            registerSkippedPreOperationPlugins(i, preOperationBindPlugins,
2623                bindOperation);
2624    
2625            return PluginResult.PreOperation.stopProcessing(
2626                DirectoryServer.getServerErrorResultCode(), message);
2627          }
2628          else if (!result.continuePluginProcessing())
2629          {
2630            registerSkippedPreOperationPlugins(i, preOperationBindPlugins,
2631                bindOperation);
2632    
2633            return result;
2634          }
2635        }
2636    
2637        if (result == null)
2638        {
2639          // This should only happen if there were no pre-operation add plugins
2640          // registered, which is fine.
2641          result = PluginResult.PreOperation.continueOperationProcessing();
2642        }
2643    
2644        return result;
2645      }
2646    
2647    
2648    
2649      /**
2650       * Invokes the set of pre-operation compare plugins that have been configured
2651       * in the Directory Server.
2652       *
2653       * @param  compareOperation  The compare operation for which to invoke the
2654       *                           pre-operation plugins.
2655       *
2656       * @return  The result of processing the pre-operation compare plugins.
2657       *
2658       * @throws CanceledOperationException if the operation should be canceled.
2659       */
2660      public PluginResult.PreOperation invokePreOperationComparePlugins(
2661         PreOperationCompareOperation compareOperation)
2662          throws CanceledOperationException {
2663        PluginResult.PreOperation result = null;
2664    
2665        for (int i = 0; i < preOperationComparePlugins.length; i++)
2666        {
2667          DirectoryServerPlugin p = preOperationComparePlugins[i];
2668          if (compareOperation.isInternalOperation() &&
2669              (! p.invokeForInternalOperations()))
2670          {
2671            continue;
2672          }
2673    
2674          try
2675          {
2676            result = p.doPreOperation(compareOperation);
2677          }
2678          catch (CanceledOperationException coe)
2679          {
2680            throw coe;
2681          }
2682          catch (Exception e)
2683          {
2684            if (debugEnabled())
2685            {
2686              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2687            }
2688    
2689            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2690                get(compareOperation.getOperationType().getOperationName(),
2691                    String.valueOf(p.getPluginEntryDN()),
2692                    compareOperation.getConnectionID(),
2693                    compareOperation.getOperationID(),
2694                    stackTraceToSingleLineString(e));
2695            logError(message);
2696    
2697            registerSkippedPreOperationPlugins(i, preOperationComparePlugins,
2698                compareOperation);
2699    
2700            return PluginResult.PreOperation.stopProcessing(
2701                DirectoryServer.getServerErrorResultCode(), message);
2702          }
2703    
2704          if (result == null)
2705          {
2706            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2707                get(compareOperation.getOperationType().getOperationName(),
2708                    String.valueOf(p.getPluginEntryDN()),
2709                    compareOperation.getConnectionID(),
2710                    compareOperation.getOperationID());
2711            logError(message);
2712    
2713            registerSkippedPreOperationPlugins(i, preOperationComparePlugins,
2714                compareOperation);
2715    
2716            return PluginResult.PreOperation.stopProcessing(
2717                DirectoryServer.getServerErrorResultCode(), message);
2718          }
2719          else if (!result.continuePluginProcessing())
2720          {
2721            return result;
2722          }
2723        }
2724    
2725        if (result == null)
2726        {
2727          // This should only happen if there were no pre-operation add plugins
2728          // registered, which is fine.
2729          result = PluginResult.PreOperation.continueOperationProcessing();
2730        }
2731    
2732        return result;
2733      }
2734    
2735    
2736    
2737      /**
2738       * Invokes the set of pre-operation delete plugins that have been configured
2739       * in the Directory Server.
2740       *
2741       * @param  deleteOperation  The delete operation for which to invoke the
2742       *                          pre-operation plugins.
2743       *
2744       * @return  The result of processing the pre-operation delete plugins.
2745       *
2746       * @throws CanceledOperationException if the operation should be canceled.
2747       */
2748      public PluginResult.PreOperation invokePreOperationDeletePlugins(
2749                                      PreOperationDeleteOperation deleteOperation)
2750          throws CanceledOperationException {
2751        PluginResult.PreOperation result = null;
2752    
2753        for (int i = 0; i < preOperationDeletePlugins.length; i++)
2754        {
2755          DirectoryServerPlugin p = preOperationDeletePlugins[i];
2756          if (deleteOperation.isInternalOperation() &&
2757              (! p.invokeForInternalOperations()))
2758          {
2759            continue;
2760          }
2761    
2762          try
2763          {
2764            result = p.doPreOperation(deleteOperation);
2765          }
2766          catch (CanceledOperationException coe)
2767          {
2768            throw coe;
2769          }
2770          catch (Exception e)
2771          {
2772            if (debugEnabled())
2773            {
2774              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2775            }
2776    
2777            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2778                get(deleteOperation.getOperationType().getOperationName(),
2779                    String.valueOf(p.getPluginEntryDN()),
2780                    deleteOperation.getConnectionID(),
2781                    deleteOperation.getOperationID(),
2782                    stackTraceToSingleLineString(e));
2783            logError(message);
2784    
2785            registerSkippedPreOperationPlugins(i, preOperationDeletePlugins,
2786                deleteOperation);
2787    
2788            return PluginResult.PreOperation.stopProcessing(
2789                DirectoryServer.getServerErrorResultCode(), message);
2790          }
2791    
2792          if (result == null)
2793          {
2794            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2795                get(deleteOperation.getOperationType().getOperationName(),
2796                    String.valueOf(p.getPluginEntryDN()),
2797                    deleteOperation.getConnectionID(),
2798                    deleteOperation.getOperationID());
2799            logError(message);
2800    
2801            registerSkippedPreOperationPlugins(i, preOperationDeletePlugins,
2802                deleteOperation);
2803    
2804            return PluginResult.PreOperation.stopProcessing(
2805                DirectoryServer.getServerErrorResultCode(), message);
2806          }
2807          else if (!result.continuePluginProcessing())
2808          {
2809            registerSkippedPreOperationPlugins(i, preOperationDeletePlugins,
2810                deleteOperation);
2811    
2812            return result;
2813          }
2814        }
2815    
2816        if (result == null)
2817        {
2818          // This should only happen if there were no pre-operation add plugins
2819          // registered, which is fine.
2820          result = PluginResult.PreOperation.continueOperationProcessing();
2821        }
2822    
2823        return result;
2824      }
2825    
2826    
2827    
2828      /**
2829       * Invokes the set of pre-operation extended plugins that have been configured
2830       * in the Directory Server.
2831       *
2832       * @param  extendedOperation  The extended operation for which to invoke the
2833       *                            pre-operation plugins.
2834       *
2835       * @return  The result of processing the pre-operation extended plugins.
2836       *
2837       * @throws CanceledOperationException if the operation should be canceled.
2838       */
2839      public PluginResult.PreOperation invokePreOperationExtendedPlugins(
2840                                   PreOperationExtendedOperation extendedOperation)
2841          throws CanceledOperationException {
2842        PluginResult.PreOperation result = null;
2843    
2844        for (int i = 0; i < preOperationExtendedPlugins.length; i++)
2845        {
2846          DirectoryServerPlugin p = preOperationExtendedPlugins[i];
2847          if (extendedOperation.isInternalOperation() &&
2848              (! p.invokeForInternalOperations()))
2849          {
2850            registerSkippedPreOperationPlugin(p, extendedOperation);
2851            continue;
2852          }
2853    
2854          try
2855          {
2856            result = p.doPreOperation(extendedOperation);
2857          }
2858          catch (CanceledOperationException coe)
2859          {
2860            throw coe;
2861          }
2862          catch (Exception e)
2863          {
2864            if (debugEnabled())
2865            {
2866              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2867            }
2868    
2869            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2870                get(extendedOperation.getOperationType().getOperationName(),
2871                    String.valueOf(p.getPluginEntryDN()),
2872                    extendedOperation.getConnectionID(),
2873                    extendedOperation.getOperationID(),
2874                    stackTraceToSingleLineString(e));
2875            logError(message);
2876    
2877            registerSkippedPreOperationPlugins(i, preOperationExtendedPlugins,
2878                extendedOperation);
2879    
2880            return PluginResult.PreOperation.stopProcessing(
2881                DirectoryServer.getServerErrorResultCode(), message);
2882          }
2883    
2884          if (result == null)
2885          {
2886            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2887                get(extendedOperation.getOperationType().getOperationName(),
2888                    String.valueOf(p.getPluginEntryDN()),
2889                    extendedOperation.getConnectionID(),
2890                    extendedOperation.getOperationID());
2891            logError(message);
2892    
2893            registerSkippedPreOperationPlugins(i, preOperationExtendedPlugins,
2894                extendedOperation);
2895    
2896            return PluginResult.PreOperation.stopProcessing(
2897                DirectoryServer.getServerErrorResultCode(), message);
2898          }
2899          else if (!result.continuePluginProcessing())
2900          {
2901            registerSkippedPreOperationPlugins(i, preOperationExtendedPlugins,
2902                extendedOperation);
2903    
2904            return result;
2905          }
2906        }
2907    
2908        if (result == null)
2909        {
2910          // This should only happen if there were no pre-operation add plugins
2911          // registered, which is fine.
2912          result = PluginResult.PreOperation.continueOperationProcessing();
2913        }
2914    
2915        return result;
2916      }
2917    
2918    
2919    
2920      /**
2921       * Invokes the set of pre-operation modify plugins that have been configured
2922       * in the Directory Server.
2923       *
2924       * @param  modifyOperation  The modify operation for which to invoke the
2925       *                          pre-operation plugins.
2926       *
2927       * @return  The result of processing the pre-operation modify plugins.
2928       *
2929       * @throws CanceledOperationException if the operation should be canceled.
2930       */
2931      public PluginResult.PreOperation invokePreOperationModifyPlugins(
2932                                      PreOperationModifyOperation modifyOperation)
2933          throws CanceledOperationException {
2934        PluginResult.PreOperation result = null;
2935    
2936        for (int i = 0; i < preOperationModifyPlugins.length; i++)
2937        {
2938          DirectoryServerPlugin p = preOperationModifyPlugins[i];
2939          if (modifyOperation.isInternalOperation() &&
2940              (! p.invokeForInternalOperations()))
2941          {
2942            continue;
2943          }
2944    
2945          try
2946          {
2947            result = p.doPreOperation(modifyOperation);
2948          }
2949          catch (CanceledOperationException coe)
2950          {
2951            throw coe;
2952          }
2953          catch (Exception e)
2954          {
2955            if (debugEnabled())
2956            {
2957              TRACER.debugCaught(DebugLogLevel.ERROR, e);
2958            }
2959    
2960            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
2961                get(modifyOperation.getOperationType().getOperationName(),
2962                    String.valueOf(p.getPluginEntryDN()),
2963                    modifyOperation.getConnectionID(),
2964                    modifyOperation.getOperationID(),
2965                    stackTraceToSingleLineString(e));
2966            logError(message);
2967    
2968            registerSkippedPreOperationPlugins(i, preOperationModifyPlugins,
2969                modifyOperation);
2970    
2971            return PluginResult.PreOperation.stopProcessing(
2972                DirectoryServer.getServerErrorResultCode(), message);
2973          }
2974    
2975          if (result == null)
2976          {
2977            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
2978                get(modifyOperation.getOperationType().getOperationName(),
2979                    String.valueOf(p.getPluginEntryDN()),
2980                    modifyOperation.getConnectionID(),
2981                    modifyOperation.getOperationID());
2982            logError(message);
2983    
2984            registerSkippedPreOperationPlugins(i, preOperationModifyPlugins,
2985                modifyOperation);
2986    
2987            return PluginResult.PreOperation.stopProcessing(
2988                DirectoryServer.getServerErrorResultCode(), message);
2989          }
2990          else if (!result.continuePluginProcessing())
2991          {
2992            registerSkippedPreOperationPlugins(i, preOperationModifyPlugins,
2993                modifyOperation);
2994    
2995            return result;
2996          }
2997        }
2998    
2999        if (result == null)
3000        {
3001          // This should only happen if there were no pre-operation add plugins
3002          // registered, which is fine.
3003          result = PluginResult.PreOperation.continueOperationProcessing();
3004        }
3005    
3006        return result;
3007      }
3008    
3009    
3010    
3011      /**
3012       * Invokes the set of pre-operation modify DN plugins that have been
3013       * configured in the Directory Server.
3014       *
3015       * @param  modifyDNOperation  The modify DN operation for which to invoke the
3016       *                            pre-operation plugins.
3017       *
3018       * @return  The result of processing the pre-operation modify DN plugins.
3019       *
3020       * @throws CanceledOperationException if the operation should be canceled.
3021       */
3022      public PluginResult.PreOperation invokePreOperationModifyDNPlugins(
3023                                  PreOperationModifyDNOperation modifyDNOperation)
3024          throws CanceledOperationException {
3025        PluginResult.PreOperation result = null;
3026    
3027        for (int i = 0; i < preOperationModifyDNPlugins.length; i++)
3028        {
3029          DirectoryServerPlugin p = preOperationModifyDNPlugins[i];
3030          if (modifyDNOperation.isInternalOperation() &&
3031              (! p.invokeForInternalOperations()))
3032          {
3033            continue;
3034          }
3035    
3036          try
3037          {
3038            result = p.doPreOperation(modifyDNOperation);
3039          }
3040          catch (CanceledOperationException coe)
3041          {
3042            throw coe;
3043          }
3044          catch (Exception e)
3045          {
3046            if (debugEnabled())
3047            {
3048              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3049            }
3050    
3051            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
3052                get(modifyDNOperation.getOperationType().getOperationName(),
3053                    String.valueOf(p.getPluginEntryDN()),
3054                    modifyDNOperation.getConnectionID(),
3055                    modifyDNOperation.getOperationID(),
3056                    stackTraceToSingleLineString(e));
3057            logError(message);
3058    
3059            registerSkippedPreOperationPlugins(i, preOperationModifyDNPlugins,
3060                modifyDNOperation);
3061    
3062            return PluginResult.PreOperation.stopProcessing(
3063                DirectoryServer.getServerErrorResultCode(), message);
3064          }
3065    
3066          if (result == null)
3067          {
3068            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
3069                get(modifyDNOperation.getOperationType().getOperationName(),
3070                    String.valueOf(p.getPluginEntryDN()),
3071                    modifyDNOperation.getConnectionID(),
3072                    modifyDNOperation.getOperationID());
3073            logError(message);
3074    
3075            registerSkippedPreOperationPlugins(i, preOperationModifyDNPlugins,
3076                modifyDNOperation);
3077    
3078            return PluginResult.PreOperation.stopProcessing(
3079                DirectoryServer.getServerErrorResultCode(), message);
3080          }
3081          else if (!result.continuePluginProcessing())
3082          {
3083            registerSkippedPreOperationPlugins(i, preOperationModifyDNPlugins,
3084                modifyDNOperation);
3085    
3086            return result;
3087          }
3088        }
3089    
3090        if (result == null)
3091        {
3092          // This should only happen if there were no pre-operation add plugins
3093          // registered, which is fine.
3094          result = PluginResult.PreOperation.continueOperationProcessing();
3095        }
3096    
3097        return result;
3098      }
3099    
3100    
3101    
3102      /**
3103       * Invokes the set of pre-operation search plugins that have been configured
3104       * in the Directory Server.
3105       *
3106       * @param  searchOperation  The search operation for which to invoke the
3107       *                          pre-operation plugins.
3108       *
3109       * @return  The result of processing the pre-operation search plugins.
3110       *
3111       * @throws CanceledOperationException if the operation should be canceled.
3112       */
3113      public PluginResult.PreOperation invokePreOperationSearchPlugins(
3114                                      PreOperationSearchOperation searchOperation)
3115          throws CanceledOperationException {
3116        PluginResult.PreOperation result = null;
3117    
3118        for (int i = 0; i < preOperationSearchPlugins.length; i++)
3119        {
3120          DirectoryServerPlugin p = preOperationSearchPlugins[i];
3121          if (searchOperation.isInternalOperation() &&
3122              (! p.invokeForInternalOperations()))
3123          {
3124            continue;
3125          }
3126    
3127          try
3128          {
3129            result = p.doPreOperation(searchOperation);
3130          }
3131          catch (CanceledOperationException coe)
3132          {
3133            throw coe;
3134          }
3135          catch (Exception e)
3136          {
3137            if (debugEnabled())
3138            {
3139              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3140            }
3141    
3142            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_EXCEPTION.
3143                get(searchOperation.getOperationType().getOperationName(),
3144                    String.valueOf(p.getPluginEntryDN()),
3145                    searchOperation.getConnectionID(),
3146                    searchOperation.getOperationID(),
3147                    stackTraceToSingleLineString(e));
3148            logError(message);
3149    
3150            registerSkippedPreOperationPlugins(i, preOperationSearchPlugins,
3151                 searchOperation);
3152    
3153            return PluginResult.PreOperation.stopProcessing(
3154                DirectoryServer.getServerErrorResultCode(), message);
3155          }
3156    
3157          if (result == null)
3158          {
3159            Message message = ERR_PLUGIN_PRE_OPERATION_PLUGIN_RETURNED_NULL.
3160                get(searchOperation.getOperationType().getOperationName(),
3161                    String.valueOf(p.getPluginEntryDN()),
3162                    searchOperation.getConnectionID(),
3163                    searchOperation.getOperationID());
3164            logError(message);
3165    
3166            registerSkippedPreOperationPlugins(i, preOperationSearchPlugins,
3167                 searchOperation);
3168    
3169            return PluginResult.PreOperation.stopProcessing(
3170                DirectoryServer.getServerErrorResultCode(), message);
3171          }
3172          else if (!result.continuePluginProcessing())
3173          {
3174            registerSkippedPreOperationPlugins(i, preOperationSearchPlugins,
3175                 searchOperation);
3176    
3177            return result;
3178          }
3179        }
3180    
3181        if (result == null)
3182        {
3183          // This should only happen if there were no pre-operation add plugins
3184          // registered, which is fine.
3185          result = PluginResult.PreOperation.continueOperationProcessing();
3186        }
3187    
3188        return result;
3189      }
3190    
3191    
3192    
3193      /**
3194       * Invokes the set of post-operation abandon plugins that have been configured
3195       * in the Directory Server.
3196       *
3197       * @param  abandonOperation  The abandon operation for which to invoke the
3198       *                           post-operation plugins.
3199       *
3200       * @return  The result of processing the post-operation abandon plugins.
3201       */
3202      public PluginResult.PostOperation invokePostOperationAbandonPlugins(
3203                                  PostOperationAbandonOperation abandonOperation)
3204      {
3205        PluginResult.PostOperation result = null;
3206        PluginResult.PostOperation finalResult = null;
3207    
3208        for (DirectoryServerPlugin p : postOperationAbandonPlugins)
3209        {
3210          if (abandonOperation.isInternalOperation() &&
3211              (! p.invokeForInternalOperations()))
3212          {
3213            continue;
3214          }
3215    
3216          try
3217          {
3218            result = p.doPostOperation(abandonOperation);
3219          }
3220          catch (Exception e)
3221          {
3222            if (debugEnabled())
3223            {
3224              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3225            }
3226    
3227            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3228                get(abandonOperation.getOperationType().getOperationName(),
3229                    String.valueOf(p.getPluginEntryDN()),
3230                    abandonOperation.getConnectionID(),
3231                    abandonOperation.getOperationID(),
3232                    stackTraceToSingleLineString(e));
3233            logError(message);
3234          }
3235    
3236          if (result == null)
3237          {
3238            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3239                get(abandonOperation.getOperationType().getOperationName(),
3240                    String.valueOf(p.getPluginEntryDN()),
3241                    abandonOperation.getConnectionID(),
3242                    abandonOperation.getOperationID());
3243            logError(message);
3244          }
3245          else if (!result.continueProcessing())
3246          {
3247            // This plugin requested operation processing to stop. However, we
3248            // still have to invoke all the post op plugins that successfully
3249            // invoked its pre op plugins. We will just take this plugin's
3250            // results as the final result.
3251            finalResult = result;
3252          }
3253        }
3254    
3255        if (result == null)
3256        {
3257          // This should only happen if there were no post-operation add plugins
3258          // registered, which is fine.
3259          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3260        }
3261        else if(finalResult == null)
3262        {
3263          // None of the plugins requested processing to stop so all results
3264          // have equal priority. Just return the last one.
3265          finalResult = result;
3266        }
3267    
3268        return finalResult;
3269      }
3270    
3271    
3272    
3273      /**
3274       * Invokes the set of post-operation add plugins that have been configured in
3275       * the Directory Server.
3276       *
3277       * @param  addOperation  The add operation for which to invoke the
3278       *                       post-operation plugins.
3279       *
3280       * @return  The result of processing the post-operation add plugins.
3281       */
3282      public PluginResult.PostOperation invokePostOperationAddPlugins(
3283                                            PostOperationAddOperation addOperation)
3284      {
3285        PluginResult.PostOperation result = null;
3286        PluginResult.PostOperation finalResult = null;
3287    
3288        for (DirectoryServerPlugin p : postOperationAddPlugins)
3289        {
3290          if (addOperation.isInternalOperation() &&
3291              (! p.invokeForInternalOperations()))
3292          {
3293            continue;
3294          }
3295    
3296          ArrayList<DirectoryServerPlugin> skippedPlugins =
3297              skippedPreOperationPlugins.remove(addOperation);
3298          if(skippedPlugins != null && skippedPlugins.contains(p))
3299          {
3300            continue;
3301          }
3302    
3303          try
3304          {
3305            result = p.doPostOperation(addOperation);
3306          }
3307          catch (Exception e)
3308          {
3309            if (debugEnabled())
3310            {
3311              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3312            }
3313    
3314            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3315                get(addOperation.getOperationType().getOperationName(),
3316                    String.valueOf(p.getPluginEntryDN()),
3317                    addOperation.getConnectionID(), addOperation.getOperationID(),
3318                    stackTraceToSingleLineString(e));
3319            logError(message);
3320          }
3321    
3322          if (result == null)
3323          {
3324            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3325                get(addOperation.getOperationType().getOperationName(),
3326                    String.valueOf(p.getPluginEntryDN()),
3327                    addOperation.getConnectionID(), addOperation.getOperationID());
3328            logError(message);
3329          }
3330          else if (!result.continueProcessing())
3331          {
3332            // This plugin requested operation processing to stop. However, we
3333            // still have to invoke all the post op plugins that successfully
3334            // invoked its pre op plugins. We will just take this plugin's
3335            // results as the final result.
3336            finalResult = result;
3337          }
3338        }
3339    
3340        if (result == null)
3341        {
3342          // This should only happen if there were no post-operation add plugins
3343          // registered, which is fine.
3344          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3345        }
3346        else if(finalResult == null)
3347        {
3348          // None of the plugins requested processing to stop so all results
3349          // have equal priority. Just return the last one.
3350          finalResult = result;
3351        }
3352    
3353        return finalResult;
3354      }
3355    
3356    
3357    
3358      /**
3359       * Invokes the set of post-operation bind plugins that have been configured
3360       * in the Directory Server.
3361       *
3362       * @param  bindOperation  The bind operation for which to invoke the
3363       *                        post-operation plugins.
3364       *
3365       * @return  The result of processing the post-operation bind plugins.
3366       */
3367      public PluginResult.PostOperation invokePostOperationBindPlugins(
3368                                       PostOperationBindOperation bindOperation)
3369      {
3370        PluginResult.PostOperation result = null;
3371        PluginResult.PostOperation finalResult = null;
3372    
3373        for (DirectoryServerPlugin p : postOperationBindPlugins)
3374        {
3375          if (bindOperation.isInternalOperation() &&
3376              (! p.invokeForInternalOperations()))
3377          {
3378            continue;
3379          }
3380    
3381          ArrayList<DirectoryServerPlugin> skippedPlugins =
3382              skippedPreOperationPlugins.remove(bindOperation);
3383          if(skippedPlugins != null && skippedPlugins.contains(p))
3384          {
3385            continue;
3386          }
3387    
3388          try
3389          {
3390            result = p.doPostOperation(bindOperation);
3391          }
3392          catch (Exception e)
3393          {
3394            if (debugEnabled())
3395            {
3396              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3397            }
3398    
3399            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3400                get(bindOperation.getOperationType().getOperationName(),
3401                    String.valueOf(p.getPluginEntryDN()),
3402                    bindOperation.getConnectionID(), bindOperation.getOperationID(),
3403                    stackTraceToSingleLineString(e));
3404            logError(message);
3405          }
3406    
3407          if (result == null)
3408          {
3409            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3410                get(bindOperation.getOperationType().getOperationName(),
3411                    String.valueOf(p.getPluginEntryDN()),
3412                    bindOperation.getConnectionID(),
3413                    bindOperation.getOperationID());
3414            logError(message);
3415          }
3416          else if (!result.continueProcessing())
3417          {
3418            // This plugin requested operation processing to stop. However, we
3419            // still have to invoke all the post op plugins that successfully
3420            // invoked its pre op plugins. We will just take this plugin's
3421            // results as the final result.
3422            finalResult = result;
3423          }
3424        }
3425    
3426        if (result == null)
3427        {
3428          // This should only happen if there were no post-operation add plugins
3429          // registered, which is fine.
3430          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3431        }
3432        else if(finalResult == null)
3433        {
3434          // None of the plugins requested processing to stop so all results
3435          // have equal priority. Just return the last one.
3436          finalResult = result;
3437        }
3438    
3439        return finalResult;
3440      }
3441    
3442    
3443    
3444      /**
3445       * Invokes the set of post-operation compare plugins that have been configured
3446       * in the Directory Server.
3447       *
3448       * @param  compareOperation  The compare operation for which to invoke the
3449       *                           post-operation plugins.
3450       *
3451       * @return  The result of processing the post-operation compare plugins.
3452       */
3453      public PluginResult.PostOperation invokePostOperationComparePlugins(
3454          PostOperationCompareOperation compareOperation)
3455      {
3456        PluginResult.PostOperation result = null;
3457        PluginResult.PostOperation finalResult = null;
3458    
3459        for (DirectoryServerPlugin p : postOperationComparePlugins)
3460        {
3461          if (compareOperation.isInternalOperation() &&
3462              (! p.invokeForInternalOperations()))
3463          {
3464            continue;
3465          }
3466    
3467          ArrayList<DirectoryServerPlugin> skippedPlugins =
3468              skippedPreOperationPlugins.remove(compareOperation);
3469          if(skippedPlugins != null && skippedPlugins.contains(p))
3470          {
3471            continue;
3472          }
3473    
3474          try
3475          {
3476            result = p.doPostOperation(compareOperation);
3477          }
3478          catch (Exception e)
3479          {
3480            if (debugEnabled())
3481            {
3482              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3483            }
3484    
3485            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3486                get(compareOperation.getOperationType().getOperationName(),
3487                    String.valueOf(p.getPluginEntryDN()),
3488                    compareOperation.getConnectionID(),
3489                    compareOperation.getOperationID(),
3490                    stackTraceToSingleLineString(e));
3491            logError(message);
3492          }
3493    
3494          if (result == null)
3495          {
3496            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3497                get(compareOperation.getOperationType().getOperationName(),
3498                    String.valueOf(p.getPluginEntryDN()),
3499                    compareOperation.getConnectionID(),
3500                    compareOperation.getOperationID());
3501            logError(message);
3502          }
3503          else if (!result.continueProcessing())
3504          {
3505            // This plugin requested operation processing to stop. However, we
3506            // still have to invoke all the post op plugins that successfully
3507            // invoked its pre op plugins. We will just take this plugin's
3508            // results as the final result.
3509            finalResult = result;
3510          }
3511        }
3512    
3513        if (result == null)
3514        {
3515          // This should only happen if there were no post-operation add plugins
3516          // registered, which is fine.
3517          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3518        }
3519        else if(finalResult == null)
3520        {
3521          // None of the plugins requested processing to stop so all results
3522          // have equal priority. Just return the last one.
3523          finalResult = result;
3524        }
3525    
3526        return finalResult;
3527      }
3528    
3529    
3530    
3531      /**
3532       * Invokes the set of post-operation delete plugins that have been configured
3533       * in the Directory Server.
3534       *
3535       * @param  deleteOperation  The delete operation for which to invoke the
3536       *                          post-operation plugins.
3537       *
3538       * @return  The result of processing the post-operation delete plugins.
3539       */
3540      public PluginResult.PostOperation invokePostOperationDeletePlugins(
3541                                       PostOperationDeleteOperation deleteOperation)
3542      {
3543        PluginResult.PostOperation result = null;
3544        PluginResult.PostOperation finalResult = null;
3545    
3546        for (DirectoryServerPlugin p : postOperationDeletePlugins)
3547        {
3548          if (deleteOperation.isInternalOperation() &&
3549              (! p.invokeForInternalOperations()))
3550          {
3551            continue;
3552          }
3553    
3554          ArrayList<DirectoryServerPlugin> skippedPlugins =
3555              skippedPreOperationPlugins.remove(deleteOperation);
3556          if(skippedPlugins != null && skippedPlugins.contains(p))
3557          {
3558            continue;
3559          }
3560    
3561          try
3562          {
3563            result = p.doPostOperation(deleteOperation);
3564          }
3565          catch (Exception e)
3566          {
3567            if (debugEnabled())
3568            {
3569              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3570            }
3571    
3572            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3573                get(deleteOperation.getOperationType().getOperationName(),
3574                    String.valueOf(p.getPluginEntryDN()),
3575                    deleteOperation.getConnectionID(),
3576                    deleteOperation.getOperationID(),
3577                    stackTraceToSingleLineString(e));
3578            logError(message);
3579          }
3580    
3581          if (result == null)
3582          {
3583            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3584                get(deleteOperation.getOperationType().getOperationName(),
3585                    String.valueOf(p.getPluginEntryDN()),
3586                    deleteOperation.getConnectionID(),
3587                    deleteOperation.getOperationID());
3588            logError(message);
3589          }
3590          else if (!result.continueProcessing())
3591          {
3592            // This plugin requested operation processing to stop. However, we
3593            // still have to invoke all the post op plugins that successfully
3594            // invoked its pre op plugins. We will just take this plugin's
3595            // results as the final result.
3596            finalResult = result;
3597          }
3598        }
3599    
3600        if (result == null)
3601        {
3602          // This should only happen if there were no post-operation add plugins
3603          // registered, which is fine.
3604          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3605        }
3606        else if(finalResult == null)
3607        {
3608          // None of the plugins requested processing to stop so all results
3609          // have equal priority. Just return the last one.
3610          finalResult = result;
3611        }
3612    
3613        return finalResult;
3614      }
3615    
3616    
3617    
3618      /**
3619       * Invokes the set of post-operation extended plugins that have been
3620       * configured in the Directory Server.
3621       *
3622       * @param  extendedOperation  The extended operation for which to invoke the
3623       *                            post-operation plugins.
3624       *
3625       * @return  The result of processing the post-operation extended plugins.
3626       */
3627      public PluginResult.PostOperation invokePostOperationExtendedPlugins(
3628                                 PostOperationExtendedOperation extendedOperation)
3629      {
3630        PluginResult.PostOperation result = null;
3631        PluginResult.PostOperation finalResult = null;
3632    
3633        for (DirectoryServerPlugin p : postOperationExtendedPlugins)
3634        {
3635          if (extendedOperation.isInternalOperation() &&
3636              (! p.invokeForInternalOperations()))
3637          {
3638            continue;
3639          }
3640    
3641          ArrayList<DirectoryServerPlugin> skippedPlugins =
3642              skippedPreOperationPlugins.remove(extendedOperation);
3643          if(skippedPlugins != null && skippedPlugins.contains(p))
3644          {
3645            continue;
3646          }
3647    
3648          try
3649          {
3650            result = p.doPostOperation(extendedOperation);
3651          }
3652          catch (Exception e)
3653          {
3654            if (debugEnabled())
3655            {
3656              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3657            }
3658    
3659            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3660                get(extendedOperation.getOperationType().getOperationName(),
3661                    String.valueOf(p.getPluginEntryDN()),
3662                    extendedOperation.getConnectionID(),
3663                    extendedOperation.getOperationID(),
3664                    stackTraceToSingleLineString(e));
3665            logError(message);
3666          }
3667    
3668          if (result == null)
3669          {
3670            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3671                get(extendedOperation.getOperationType().getOperationName(),
3672                    String.valueOf(p.getPluginEntryDN()),
3673                    extendedOperation.getConnectionID(),
3674                    extendedOperation.getOperationID());
3675            logError(message);
3676          }
3677          else if (!result.continueProcessing())
3678          {
3679            // This plugin requested operation processing to stop. However, we
3680            // still have to invoke all the post op plugins that successfully
3681            // invoked its pre op plugins. We will just take this plugin's
3682            // results as the final result.
3683            finalResult = result;
3684          }
3685        }
3686    
3687        if (result == null)
3688        {
3689          // This should only happen if there were no post-operation add plugins
3690          // registered, which is fine.
3691          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3692        }
3693        else if(finalResult == null)
3694        {
3695          // None of the plugins requested processing to stop so all results
3696          // have equal priority. Just return the last one.
3697          finalResult = result;
3698        }
3699    
3700        return finalResult;
3701      }
3702    
3703    
3704    
3705      /**
3706       * Invokes the set of post-operation modify plugins that have been configured
3707       * in the Directory Server.
3708       *
3709       * @param  modifyOperation  The modify operation for which to invoke the
3710       *                          post-operation plugins.
3711       *
3712       * @return  The result of processing the post-operation modify plugins.
3713       */
3714      public PluginResult.PostOperation invokePostOperationModifyPlugins(
3715                                       PostOperationModifyOperation modifyOperation)
3716      {
3717        PluginResult.PostOperation result = null;
3718        PluginResult.PostOperation finalResult = null;
3719    
3720        for (DirectoryServerPlugin p : postOperationModifyPlugins)
3721        {
3722          if (modifyOperation.isInternalOperation() &&
3723              (! p.invokeForInternalOperations()))
3724          {
3725            continue;
3726          }
3727    
3728          ArrayList<DirectoryServerPlugin> skippedPlugins =
3729              skippedPreOperationPlugins.remove(modifyOperation);
3730          if(skippedPlugins != null && skippedPlugins.contains(p))
3731          {
3732            continue;
3733          }
3734    
3735          try
3736          {
3737            result = p.doPostOperation(modifyOperation);
3738          }
3739          catch (Exception e)
3740          {
3741            if (debugEnabled())
3742            {
3743              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3744            }
3745    
3746            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3747                get(modifyOperation.getOperationType().getOperationName(),
3748                    String.valueOf(p.getPluginEntryDN()),
3749                    modifyOperation.getConnectionID(),
3750                    modifyOperation.getOperationID(),
3751                    stackTraceToSingleLineString(e));
3752            logError(message);
3753          }
3754    
3755          if (result == null)
3756          {
3757            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3758                get(modifyOperation.getOperationType().getOperationName(),
3759                    String.valueOf(p.getPluginEntryDN()),
3760                    modifyOperation.getConnectionID(),
3761                    modifyOperation.getOperationID());
3762            logError(message);
3763          }
3764          else if (!result.continueProcessing())
3765          {
3766            // This plugin requested operation processing to stop. However, we
3767            // still have to invoke all the post op plugins that successfully
3768            // invoked its pre op plugins. We will just take this plugin's
3769            // results as the final result.
3770            finalResult = result;
3771          }
3772        }
3773    
3774        if (result == null)
3775        {
3776          // This should only happen if there were no post-operation add plugins
3777          // registered, which is fine.
3778          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3779        }
3780        else if(finalResult == null)
3781        {
3782          // None of the plugins requested processing to stop so all results
3783          // have equal priority. Just return the last one.
3784          finalResult = result;
3785        }
3786        return finalResult;
3787      }
3788    
3789    
3790    
3791      /**
3792       * Invokes the set of post-operation modify DN plugins that have been
3793       * configured in the Directory Server.
3794       *
3795       * @param  modifyDNOperation  The modify DN operation for which to invoke the
3796       *                            post-operation plugins.
3797       *
3798       * @return  The result of processing the post-operation modify DN plugins.
3799       */
3800      public PluginResult.PostOperation invokePostOperationModifyDNPlugins(
3801                                 PostOperationModifyDNOperation modifyDNOperation)
3802      {
3803        PluginResult.PostOperation result = null;
3804        PluginResult.PostOperation finalResult = null;
3805    
3806        for (DirectoryServerPlugin p : postOperationModifyDNPlugins)
3807        {
3808          if (modifyDNOperation.isInternalOperation() &&
3809              (! p.invokeForInternalOperations()))
3810          {
3811            continue;
3812          }
3813    
3814          ArrayList<DirectoryServerPlugin> skippedPlugins =
3815              skippedPreOperationPlugins.remove(modifyDNOperation);
3816          if(skippedPlugins != null && skippedPlugins.contains(p))
3817          {
3818            continue;
3819          }
3820    
3821          try
3822          {
3823            result = p.doPostOperation(modifyDNOperation);
3824          }
3825          catch (Exception e)
3826          {
3827            if (debugEnabled())
3828            {
3829              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3830            }
3831    
3832            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3833                get(modifyDNOperation.getOperationType().getOperationName(),
3834                    String.valueOf(p.getPluginEntryDN()),
3835                    modifyDNOperation.getConnectionID(),
3836                    modifyDNOperation.getOperationID(),
3837                    stackTraceToSingleLineString(e));
3838            logError(message);
3839          }
3840    
3841          if (result == null)
3842          {
3843            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3844                get(modifyDNOperation.getOperationType().getOperationName(),
3845                    String.valueOf(p.getPluginEntryDN()),
3846                    modifyDNOperation.getConnectionID(),
3847                    modifyDNOperation.getOperationID());
3848            logError(message);
3849          }
3850          else if (!result.continueProcessing())
3851          {
3852            // This plugin requested operation processing to stop. However, we
3853            // still have to invoke all the post op plugins that successfully
3854            // invoked its pre op plugins. We will just take this plugin's
3855            // results as the final result.
3856            finalResult = result;
3857          }
3858        }
3859    
3860        if (result == null)
3861        {
3862          // This should only happen if there were no post-operation add plugins
3863          // registered, which is fine.
3864          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3865        }
3866        else if(finalResult == null)
3867        {
3868          // None of the plugins requested processing to stop so all results
3869          // have equal priority. Just return the last one.
3870          finalResult = result;
3871        }
3872    
3873        return finalResult;
3874      }
3875    
3876    
3877    
3878      /**
3879       * Invokes the set of post-operation search plugins that have been configured
3880       * in the Directory Server.
3881       *
3882       * @param  searchOperation  The search operation for which to invoke the
3883       *                          post-operation plugins.
3884       *
3885       * @return  The result of processing the post-operation search plugins.
3886       */
3887      public PluginResult.PostOperation invokePostOperationSearchPlugins(
3888                                       PostOperationSearchOperation searchOperation)
3889      {
3890        PluginResult.PostOperation result = null;
3891        PluginResult.PostOperation finalResult = null;
3892    
3893        for (DirectoryServerPlugin p : postOperationSearchPlugins)
3894        {
3895          if (searchOperation.isInternalOperation() &&
3896              (! p.invokeForInternalOperations()))
3897          {
3898            continue;
3899          }
3900    
3901          ArrayList<DirectoryServerPlugin> skippedPlugins =
3902              skippedPreOperationPlugins.remove(searchOperation);
3903          if(skippedPlugins != null && skippedPlugins.contains(p))
3904          {
3905            continue;
3906          }
3907    
3908          try
3909          {
3910            result = p.doPostOperation(searchOperation);
3911          }
3912          catch (Exception e)
3913          {
3914            if (debugEnabled())
3915            {
3916              TRACER.debugCaught(DebugLogLevel.ERROR, e);
3917            }
3918    
3919            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
3920                get(searchOperation.getOperationType().getOperationName(),
3921                    String.valueOf(p.getPluginEntryDN()),
3922                    searchOperation.getConnectionID(),
3923                    searchOperation.getOperationID(),
3924                    stackTraceToSingleLineString(e));
3925            logError(message);
3926          }
3927    
3928          if (result == null)
3929          {
3930            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
3931                get(searchOperation.getOperationType().getOperationName(),
3932                    String.valueOf(p.getPluginEntryDN()),
3933                    searchOperation.getConnectionID(),
3934                    searchOperation.getOperationID());
3935            logError(message);
3936          }
3937          else if (!result.continueProcessing())
3938          {
3939            // This plugin requested operation processing to stop. However, we
3940            // still have to invoke all the post op plugins that successfully
3941            // invoked its pre op plugins. We will just take this plugin's
3942            // results as the final result.
3943            finalResult = result;
3944          }
3945        }
3946    
3947        if (result == null)
3948        {
3949          // This should only happen if there were no post-operation add plugins
3950          // registered, which is fine.
3951          finalResult = PluginResult.PostOperation.continueOperationProcessing();
3952        }
3953        else if(finalResult == null)
3954        {
3955          // None of the plugins requested processing to stop so all results
3956          // have equal priority. Just return the last one.
3957          finalResult = result;
3958        }
3959    
3960        return finalResult;
3961      }
3962    
3963    
3964    
3965      /**
3966       * Invokes the set of post-operation unbind plugins that have been configured
3967       * in the Directory Server.
3968       *
3969       * @param  unbindOperation  The unbind operation for which to invoke the
3970       *                          post-operation plugins.
3971       *
3972       * @return  The result of processing the post-operation unbind plugins.
3973       */
3974      public PluginResult.PostOperation invokePostOperationUnbindPlugins(
3975                                     PostOperationUnbindOperation unbindOperation)
3976      {
3977        PluginResult.PostOperation result = null;
3978        PluginResult.PostOperation finalResult = null;
3979    
3980        for (DirectoryServerPlugin p : postOperationUnbindPlugins)
3981        {
3982          if (unbindOperation.isInternalOperation() &&
3983              (! p.invokeForInternalOperations()))
3984          {
3985            continue;
3986          }
3987    
3988          ArrayList<DirectoryServerPlugin> skippedPlugins =
3989              skippedPreOperationPlugins.remove(unbindOperation);
3990          if(skippedPlugins != null && skippedPlugins.contains(p))
3991          {
3992            continue;
3993          }
3994    
3995          try
3996          {
3997            result = p.doPostOperation(unbindOperation);
3998          }
3999          catch (Exception e)
4000          {
4001            if (debugEnabled())
4002            {
4003              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4004            }
4005    
4006            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_EXCEPTION.
4007                get(unbindOperation.getOperationType().getOperationName(),
4008                    String.valueOf(p.getPluginEntryDN()),
4009                    unbindOperation.getConnectionID(),
4010                    unbindOperation.getOperationID(),
4011                    stackTraceToSingleLineString(e));
4012            logError(message);
4013          }
4014    
4015          if (result == null)
4016          {
4017            Message message = ERR_PLUGIN_POST_OPERATION_PLUGIN_RETURNED_NULL.
4018                get(unbindOperation.getOperationType().getOperationName(),
4019                    String.valueOf(p.getPluginEntryDN()),
4020                    unbindOperation.getConnectionID(),
4021                    unbindOperation.getOperationID());
4022            logError(message);
4023          }
4024          else if (!result.continueProcessing())
4025          {
4026            // This plugin requested operation processing to stop. However, we
4027            // still have to invoke all the post op plugins that successfully
4028            // invoked its pre op plugins. We will just take this plugin's
4029            // results as the final result.
4030            finalResult = result;
4031          }
4032        }
4033    
4034        if (result == null)
4035        {
4036          // This should only happen if there were no post-operation add plugins
4037          // registered, which is fine.
4038          finalResult = PluginResult.PostOperation.continueOperationProcessing();
4039        }
4040        else if(finalResult == null)
4041        {
4042          // None of the plugins requested processing to stop so all results
4043          // have equal priority. Just return the last one.
4044          finalResult = result;
4045        }
4046    
4047        return finalResult;
4048      }
4049    
4050    
4051    
4052      /**
4053       * Invokes the set of post-response add plugins that have been configured in
4054       * the Directory Server.
4055       *
4056       * @param  addOperation  The add operation for which to invoke the
4057       *                       post-response plugins.
4058       *
4059       * @return  The result of processing the post-response add plugins.
4060       */
4061      public PluginResult.PostResponse invokePostResponseAddPlugins(
4062                                           PostResponseAddOperation addOperation)
4063      {
4064        PluginResult.PostResponse result = null;
4065    
4066        for (DirectoryServerPlugin p : postResponseAddPlugins)
4067        {
4068          if (addOperation.isInternalOperation() &&
4069              (! p.invokeForInternalOperations()))
4070          {
4071            continue;
4072          }
4073    
4074          try
4075          {
4076            result = p.doPostResponse(addOperation);
4077          }
4078          catch (Exception e)
4079          {
4080            if (debugEnabled())
4081            {
4082              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4083            }
4084    
4085            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4086                get(addOperation.getOperationType().getOperationName(),
4087                    String.valueOf(p.getPluginEntryDN()),
4088                    addOperation.getConnectionID(), addOperation.getOperationID(),
4089                    stackTraceToSingleLineString(e));
4090            logError(message);
4091          }
4092    
4093          if (result == null)
4094          {
4095            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4096                get(addOperation.getOperationType().getOperationName(),
4097                    String.valueOf(p.getPluginEntryDN()),
4098                    addOperation.getConnectionID(), addOperation.getOperationID());
4099            logError(message);
4100          }
4101          else if (!result.continuePluginProcessing())
4102          {
4103            return result;
4104          }
4105        }
4106    
4107        if (result == null)
4108        {
4109          // This should only happen if there were no post-response add plugins
4110          // registered, which is fine.
4111          result = PluginResult.PostResponse.continueOperationProcessing();
4112        }
4113    
4114        return result;
4115      }
4116    
4117    
4118    
4119      /**
4120       * Invokes the set of post-response bind plugins that have been configured in
4121       * the Directory Server.
4122       *
4123       * @param  bindOperation  The bind operation for which to invoke the
4124       *                        post-response plugins.
4125       *
4126       * @return  The result of processing the post-response bind plugins.
4127       */
4128      public PluginResult.PostResponse invokePostResponseBindPlugins(
4129                                           PostResponseBindOperation bindOperation)
4130      {
4131        PluginResult.PostResponse result = null;
4132    
4133        for (DirectoryServerPlugin p : postResponseBindPlugins)
4134        {
4135          if (bindOperation.isInternalOperation() &&
4136              (! p.invokeForInternalOperations()))
4137          {
4138            continue;
4139          }
4140    
4141          try
4142          {
4143            result = p.doPostResponse(bindOperation);
4144          }
4145          catch (Exception e)
4146          {
4147            if (debugEnabled())
4148            {
4149              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4150            }
4151    
4152            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4153                get(bindOperation.getOperationType().getOperationName(),
4154                    String.valueOf(p.getPluginEntryDN()),
4155                    bindOperation.getConnectionID(), bindOperation.getOperationID(),
4156                    stackTraceToSingleLineString(e));
4157            logError(message);
4158          }
4159    
4160          if (result == null)
4161          {
4162            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4163                get(bindOperation.getOperationType().getOperationName(),
4164                    String.valueOf(p.getPluginEntryDN()),
4165                    bindOperation.getConnectionID(),
4166                    bindOperation.getOperationID());
4167            logError(message);
4168          }
4169          else if (!result.continuePluginProcessing())
4170          {
4171            return result;
4172          }
4173        }
4174    
4175        if (result == null)
4176        {
4177          // This should only happen if there were no post-response add plugins
4178          // registered, which is fine.
4179          result = PluginResult.PostResponse.continueOperationProcessing();
4180        }
4181    
4182        return result;
4183      }
4184    
4185    
4186    
4187      /**
4188       * Invokes the set of post-response compare plugins that have been configured
4189       * in the Directory Server.
4190       *
4191       * @param  compareOperation  The compare operation for which to invoke the
4192       *                           post-response plugins.
4193       *
4194       * @return  The result of processing the post-response compare plugins.
4195       */
4196      public PluginResult.PostResponse invokePostResponseComparePlugins(
4197          PostResponseCompareOperation compareOperation)
4198      {
4199        PluginResult.PostResponse result = null;
4200    
4201        for (DirectoryServerPlugin p : postResponseComparePlugins)
4202        {
4203          if (compareOperation.isInternalOperation() &&
4204              (! p.invokeForInternalOperations()))
4205          {
4206            continue;
4207          }
4208    
4209          try
4210          {
4211            result = p.doPostResponse(compareOperation);
4212          }
4213          catch (Exception e)
4214          {
4215            if (debugEnabled())
4216            {
4217              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4218            }
4219    
4220            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4221                get(compareOperation.getOperationType().getOperationName(),
4222                    String.valueOf(p.getPluginEntryDN()),
4223                    compareOperation.getConnectionID(),
4224                    compareOperation.getOperationID(),
4225                    stackTraceToSingleLineString(e));
4226            logError(message);
4227          }
4228    
4229          if (result == null)
4230          {
4231            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4232                get(compareOperation.getOperationType().getOperationName(),
4233                    String.valueOf(p.getPluginEntryDN()),
4234                    compareOperation.getConnectionID(),
4235                    compareOperation.getOperationID());
4236            logError(message);
4237          }
4238          else if (!result.continuePluginProcessing())
4239          {
4240            return result;
4241          }
4242        }
4243    
4244        if (result == null)
4245        {
4246          // This should only happen if there were no post-response add plugins
4247          // registered, which is fine.
4248          result = PluginResult.PostResponse.continueOperationProcessing();
4249        }
4250    
4251        return result;
4252      }
4253    
4254    
4255    
4256      /**
4257       * Invokes the set of post-response delete plugins that have been configured
4258       * in the Directory Server.
4259       *
4260       * @param  deleteOperation  The delete operation for which to invoke the
4261       *                          post-response plugins.
4262       *
4263       * @return  The result of processing the post-response delete plugins.
4264       */
4265      public PluginResult.PostResponse invokePostResponseDeletePlugins(
4266                              PostResponseDeleteOperation deleteOperation)
4267      {
4268        PluginResult.PostResponse result = null;
4269    
4270        for (DirectoryServerPlugin p : postResponseDeletePlugins)
4271        {
4272          if (deleteOperation.isInternalOperation() &&
4273              (! p.invokeForInternalOperations()))
4274          {
4275            continue;
4276          }
4277    
4278          try
4279          {
4280            result = p.doPostResponse(deleteOperation);
4281          }
4282          catch (Exception e)
4283          {
4284            if (debugEnabled())
4285            {
4286              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4287            }
4288    
4289            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4290                get(deleteOperation.getOperationType().getOperationName(),
4291                    String.valueOf(p.getPluginEntryDN()),
4292                    deleteOperation.getConnectionID(),
4293                    deleteOperation.getOperationID(),
4294                    stackTraceToSingleLineString(e));
4295            logError(message);
4296          }
4297    
4298          if (result == null)
4299          {
4300            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4301                get(deleteOperation.getOperationType().getOperationName(),
4302                    String.valueOf(p.getPluginEntryDN()),
4303                    deleteOperation.getConnectionID(),
4304                    deleteOperation.getOperationID());
4305            logError(message);
4306          }
4307          else if (!result.continuePluginProcessing())
4308          {
4309            return result;
4310          }
4311        }
4312    
4313        if (result == null)
4314        {
4315          // This should only happen if there were no post-response add plugins
4316          // registered, which is fine.
4317          result = PluginResult.PostResponse.continueOperationProcessing();
4318        }
4319        return result;
4320      }
4321    
4322    
4323    
4324      /**
4325       * Invokes the set of post-response extended plugins that have been configured
4326       * in the Directory Server.
4327       *
4328       * @param  extendedOperation  The extended operation for which to invoke the
4329       *                            post-response plugins.
4330       *
4331       * @return  The result of processing the post-response extended plugins.
4332       */
4333      public PluginResult.PostResponse invokePostResponseExtendedPlugins(
4334                                  PostResponseExtendedOperation extendedOperation)
4335      {
4336        PluginResult.PostResponse result = null;
4337    
4338        for (DirectoryServerPlugin p : postResponseExtendedPlugins)
4339        {
4340          if (extendedOperation.isInternalOperation() &&
4341              (! p.invokeForInternalOperations()))
4342          {
4343            continue;
4344          }
4345    
4346          try
4347          {
4348            result = p.doPostResponse(extendedOperation);
4349          }
4350          catch (Exception e)
4351          {
4352            if (debugEnabled())
4353            {
4354              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4355            }
4356    
4357            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4358                get(extendedOperation.getOperationType().getOperationName(),
4359                    String.valueOf(p.getPluginEntryDN()),
4360                    extendedOperation.getConnectionID(),
4361                    extendedOperation.getOperationID(),
4362                    stackTraceToSingleLineString(e));
4363            logError(message);
4364          }
4365    
4366          if (result == null)
4367          {
4368            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4369                get(extendedOperation.getOperationType().getOperationName(),
4370                    String.valueOf(p.getPluginEntryDN()),
4371                    extendedOperation.getConnectionID(),
4372                    extendedOperation.getOperationID());
4373            logError(message);
4374          }
4375          else if (!result.continuePluginProcessing())
4376          {
4377            return result;
4378          }
4379        }
4380    
4381        if (result == null)
4382        {
4383          // This should only happen if there were no post-response add plugins
4384          // registered, which is fine.
4385          result = PluginResult.PostResponse.continueOperationProcessing();
4386        }
4387    
4388        return result;
4389      }
4390    
4391    
4392    
4393      /**
4394       * Invokes the set of post-response modify plugins that have been configured
4395       * in the Directory Server.
4396       *
4397       * @param  modifyOperation  The modify operation for which to invoke the
4398       *                          post-response plugins.
4399       *
4400       * @return  The result of processing the post-response modify plugins.
4401       */
4402      public PluginResult.PostResponse invokePostResponseModifyPlugins(
4403                                      PostResponseModifyOperation modifyOperation)
4404      {
4405        PluginResult.PostResponse result = null;
4406    
4407        for (DirectoryServerPlugin p : postResponseModifyPlugins)
4408        {
4409          if (modifyOperation.isInternalOperation() &&
4410              (! p.invokeForInternalOperations()))
4411          {
4412            continue;
4413          }
4414    
4415          try
4416          {
4417            result = p.doPostResponse(modifyOperation);
4418          }
4419          catch (Exception e)
4420          {
4421            if (debugEnabled())
4422            {
4423              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4424            }
4425    
4426            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4427                get(modifyOperation.getOperationType().getOperationName(),
4428                    String.valueOf(p.getPluginEntryDN()),
4429                    modifyOperation.getConnectionID(),
4430                    modifyOperation.getOperationID(),
4431                    stackTraceToSingleLineString(e));
4432            logError(message);
4433          }
4434    
4435          if (result == null)
4436          {
4437            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4438                get(modifyOperation.getOperationType().getOperationName(),
4439                    String.valueOf(p.getPluginEntryDN()),
4440                    modifyOperation.getConnectionID(),
4441                    modifyOperation.getOperationID());
4442            logError(message);
4443          }
4444          else if (!result.continuePluginProcessing())
4445          {
4446            return result;
4447          }
4448        }
4449    
4450        if (result == null)
4451        {
4452          // This should only happen if there were no post-response add plugins
4453          // registered, which is fine.
4454          result = PluginResult.PostResponse.continueOperationProcessing();
4455        }
4456    
4457        return result;
4458      }
4459    
4460    
4461    
4462      /**
4463       * Invokes the set of post-response modify DN plugins that have been
4464       * configured in the Directory Server.
4465       *
4466       * @param  modifyDNOperation  The modify DN operation for which to invoke the
4467       *                            post-response plugins.
4468       *
4469       * @return  The result of processing the post-response modify DN plugins.
4470       */
4471      public PluginResult.PostResponse invokePostResponseModifyDNPlugins(
4472                                   PostResponseModifyDNOperation modifyDNOperation)
4473      {
4474        PluginResult.PostResponse result = null;
4475    
4476        for (DirectoryServerPlugin p : postResponseModifyDNPlugins)
4477        {
4478          if (modifyDNOperation.isInternalOperation() &&
4479              (! p.invokeForInternalOperations()))
4480          {
4481            continue;
4482          }
4483    
4484          try
4485          {
4486            result = p.doPostResponse(modifyDNOperation);
4487          }
4488          catch (Exception e)
4489          {
4490            if (debugEnabled())
4491            {
4492              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4493            }
4494    
4495            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4496                get(modifyDNOperation.getOperationType().getOperationName(),
4497                    String.valueOf(p.getPluginEntryDN()),
4498                    modifyDNOperation.getConnectionID(),
4499                    modifyDNOperation.getOperationID(),
4500                    stackTraceToSingleLineString(e));
4501            logError(message);
4502          }
4503    
4504          if (result == null)
4505          {
4506            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4507                get(modifyDNOperation.getOperationType().getOperationName(),
4508                    String.valueOf(p.getPluginEntryDN()),
4509                    modifyDNOperation.getConnectionID(),
4510                    modifyDNOperation.getOperationID());
4511            logError(message);
4512          }
4513          else if (!result.continuePluginProcessing())
4514          {
4515            return result;
4516          }
4517        }
4518    
4519        if (result == null)
4520        {
4521          // This should only happen if there were no post-response add plugins
4522          // registered, which is fine.
4523          result = PluginResult.PostResponse.continueOperationProcessing();
4524        }
4525    
4526        return result;
4527      }
4528    
4529    
4530    
4531      /**
4532       * Invokes the set of post-response search plugins that have been configured
4533       * in the Directory Server.
4534       *
4535       * @param  searchOperation  The search operation for which to invoke the
4536       *                          post-response plugins.
4537       *
4538       * @return  The result of processing the post-response search plugins.
4539       */
4540      public PluginResult.PostResponse invokePostResponseSearchPlugins(
4541                                      PostResponseSearchOperation searchOperation)
4542      {
4543        PluginResult.PostResponse result = null;
4544    
4545        for (DirectoryServerPlugin p : postResponseSearchPlugins)
4546        {
4547          if (searchOperation.isInternalOperation() &&
4548              (! p.invokeForInternalOperations()))
4549          {
4550            continue;
4551          }
4552    
4553          try
4554          {
4555            result = p.doPostResponse(searchOperation);
4556          }
4557          catch (Exception e)
4558          {
4559            if (debugEnabled())
4560            {
4561              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4562            }
4563    
4564            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_EXCEPTION.
4565                get(searchOperation.getOperationType().getOperationName(),
4566                    String.valueOf(p.getPluginEntryDN()),
4567                    searchOperation.getConnectionID(),
4568                    searchOperation.getOperationID(),
4569                    stackTraceToSingleLineString(e));
4570            logError(message);
4571          }
4572    
4573          if (result == null)
4574          {
4575            Message message = ERR_PLUGIN_POST_RESPONSE_PLUGIN_RETURNED_NULL.
4576                get(searchOperation.getOperationType().getOperationName(),
4577                    String.valueOf(p.getPluginEntryDN()),
4578                    searchOperation.getConnectionID(),
4579                    searchOperation.getOperationID());
4580            logError(message);
4581          }
4582          else if (!result.continuePluginProcessing())
4583          {
4584            return result;
4585          }
4586        }
4587    
4588        if (result == null)
4589        {
4590          // This should only happen if there were no post-response add plugins
4591          // registered, which is fine.
4592          result = PluginResult.PostResponse.continueOperationProcessing();
4593        }
4594    
4595        return result;
4596      }
4597    
4598    
4599    
4600      /**
4601       * Invokes the set of post-synchronization add plugins that have been
4602       * configured in the Directory Server.
4603       *
4604       * @param  addOperation  The add operation for which to invoke the
4605       *                       post-synchronization plugins.
4606       */
4607      public void invokePostSynchronizationAddPlugins(
4608                       PostSynchronizationAddOperation addOperation)
4609      {
4610        for (DirectoryServerPlugin p : postSynchronizationAddPlugins)
4611        {
4612          try
4613          {
4614            p.doPostSynchronization(addOperation);
4615          }
4616          catch (Exception e)
4617          {
4618            if (debugEnabled())
4619            {
4620              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4621            }
4622    
4623            Message message = ERR_PLUGIN_POST_SYNCHRONIZATION_PLUGIN_EXCEPTION.
4624                get(addOperation.getOperationType().getOperationName(),
4625                    String.valueOf(p.getPluginEntryDN()),
4626                    addOperation.getConnectionID(), addOperation.getOperationID(),
4627                    stackTraceToSingleLineString(e));
4628            logError(message);
4629          }
4630        }
4631      }
4632    
4633    
4634    
4635      /**
4636       * Invokes the set of post-synchronization delete plugins that have been
4637       * configured in the Directory Server.
4638       *
4639       * @param  deleteOperation  The delete operation for which to invoke the
4640       *                          post-synchronization plugins.
4641       */
4642      public void invokePostSynchronizationDeletePlugins(
4643                       PostSynchronizationDeleteOperation deleteOperation)
4644      {
4645        for (DirectoryServerPlugin p : postSynchronizationDeletePlugins)
4646        {
4647          try
4648          {
4649            p.doPostSynchronization(deleteOperation);
4650          }
4651          catch (Exception e)
4652          {
4653            if (debugEnabled())
4654            {
4655              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4656            }
4657    
4658            Message message = ERR_PLUGIN_POST_SYNCHRONIZATION_PLUGIN_EXCEPTION.
4659                get(deleteOperation.getOperationType().getOperationName(),
4660                    String.valueOf(p.getPluginEntryDN()),
4661                    deleteOperation.getConnectionID(),
4662                    deleteOperation.getOperationID(),
4663                    stackTraceToSingleLineString(e));
4664            logError(message);
4665          }
4666        }
4667      }
4668    
4669    
4670    
4671      /**
4672       * Invokes the set of post-synchronization modify plugins that have been
4673       * configured in the Directory Server.
4674       *
4675       * @param  modifyOperation  The modify operation for which to invoke the
4676       *                          post-synchronization plugins.
4677       */
4678      public void invokePostSynchronizationModifyPlugins(
4679                       PostSynchronizationModifyOperation modifyOperation)
4680      {
4681        for (DirectoryServerPlugin p : postSynchronizationModifyPlugins)
4682        {
4683          try
4684          {
4685            p.doPostSynchronization(modifyOperation);
4686          }
4687          catch (Exception e)
4688          {
4689            if (debugEnabled())
4690            {
4691              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4692            }
4693    
4694            Message message = ERR_PLUGIN_POST_SYNCHRONIZATION_PLUGIN_EXCEPTION.
4695                get(modifyOperation.getOperationType().getOperationName(),
4696                    String.valueOf(p.getPluginEntryDN()),
4697                    modifyOperation.getConnectionID(),
4698                    modifyOperation.getOperationID(),
4699                    stackTraceToSingleLineString(e));
4700            logError(message);
4701          }
4702        }
4703      }
4704    
4705    
4706    
4707      /**
4708       * Invokes the set of post-synchronization modify DN plugins that have been
4709       * configured in the Directory Server.
4710       *
4711       * @param  modifyDNOperation  The modify DN operation for which to invoke the
4712       *                            post-synchronization plugins.
4713       */
4714      public void invokePostSynchronizationModifyDNPlugins(
4715                       PostSynchronizationModifyDNOperation modifyDNOperation)
4716      {
4717        for (DirectoryServerPlugin p : postSynchronizationModifyDNPlugins)
4718        {
4719          try
4720          {
4721            p.doPostSynchronization(modifyDNOperation);
4722          }
4723          catch (Exception e)
4724          {
4725            if (debugEnabled())
4726            {
4727              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4728            }
4729    
4730            Message message = ERR_PLUGIN_POST_SYNCHRONIZATION_PLUGIN_EXCEPTION.
4731                get(modifyDNOperation.getOperationType().getOperationName(),
4732                    String.valueOf(p.getPluginEntryDN()),
4733                    modifyDNOperation.getConnectionID(),
4734                    modifyDNOperation.getOperationID(),
4735                    stackTraceToSingleLineString(e));
4736            logError(message);
4737          }
4738        }
4739      }
4740    
4741    
4742    
4743      /**
4744       * Invokes the set of search result entry plugins that have been configured
4745       * in the Directory Server.
4746       *
4747       * @param  searchOperation  The search operation for which to invoke the
4748       *                          search result entry plugins.
4749       * @param  searchEntry      The search result entry to be processed.
4750       *
4751       * @return  The result of processing the search result entry plugins.
4752       */
4753      public PluginResult.IntermediateResponse invokeSearchResultEntryPlugins(
4754                                     LocalBackendSearchOperation searchOperation,
4755                                     SearchResultEntry searchEntry)
4756      {
4757        PluginResult.IntermediateResponse result = null;
4758    
4759        for (DirectoryServerPlugin p : searchResultEntryPlugins)
4760        {
4761          if (searchOperation.isInternalOperation() &&
4762              (! p.invokeForInternalOperations()))
4763          {
4764            continue;
4765          }
4766    
4767          try
4768          {
4769            result = p.processSearchEntry(searchOperation, searchEntry);
4770          }
4771          catch (Exception e)
4772          {
4773            if (debugEnabled())
4774            {
4775              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4776            }
4777    
4778            Message message = ERR_PLUGIN_SEARCH_ENTRY_PLUGIN_EXCEPTION.
4779                get(String.valueOf(p.getPluginEntryDN()),
4780                    searchOperation.getConnectionID(),
4781                    searchOperation.getOperationID(),
4782                    String.valueOf(searchEntry.getDN()),
4783                    stackTraceToSingleLineString(e));
4784            logError(message);
4785    
4786            return PluginResult.IntermediateResponse.stopProcessing(false,
4787                DirectoryServer.getServerErrorResultCode(), message);
4788          }
4789    
4790          if (result == null)
4791          {
4792            Message message = ERR_PLUGIN_SEARCH_ENTRY_PLUGIN_RETURNED_NULL.
4793                get(String.valueOf(p.getPluginEntryDN()),
4794                    searchOperation.getConnectionID(),
4795                    searchOperation.getOperationID(),
4796                    String.valueOf(searchEntry.getDN()));
4797            logError(message);
4798    
4799            return PluginResult.IntermediateResponse.stopProcessing(false,
4800                DirectoryServer.getServerErrorResultCode(), message);
4801          }
4802          else if (! result.continuePluginProcessing())
4803          {
4804            return result;
4805          }
4806        }
4807    
4808        if (result == null)
4809        {
4810          // This should only happen if there were no search result entry plugins
4811          // registered, which is fine.
4812          result = PluginResult.IntermediateResponse.
4813              continueOperationProcessing(true);
4814        }
4815    
4816        return result;
4817      }
4818    
4819    
4820    
4821      /**
4822       * Invokes the set of search result entry plugins that have been configured
4823       * in the Directory Server.
4824       *
4825       * @param  searchOperation  The search operation for which to invoke the
4826       *                          search result entry plugins.
4827       * @param  searchEntry      The search result entry to be processed.
4828       *
4829       * @return  The result of processing the search result entry plugins.
4830       */
4831      public PluginResult.IntermediateResponse invokeSearchResultEntryPlugins(
4832          SearchEntrySearchOperation searchOperation,
4833          SearchResultEntry searchEntry)
4834      {
4835        PluginResult.IntermediateResponse result = null;
4836    
4837        for (DirectoryServerPlugin p : searchResultEntryPlugins)
4838        {
4839          if (searchOperation.isInternalOperation() &&
4840              (! p.invokeForInternalOperations()))
4841          {
4842            continue;
4843          }
4844    
4845          if (searchOperation.isInternalOperation() &&
4846              (! p.invokeForInternalOperations()))
4847          {
4848            continue;
4849          }
4850    
4851          try
4852          {
4853            result = p.processSearchEntry(searchOperation, searchEntry);
4854          }
4855          catch (Exception e)
4856          {
4857            if (debugEnabled())
4858            {
4859              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4860            }
4861    
4862            Message message = ERR_PLUGIN_SEARCH_ENTRY_PLUGIN_EXCEPTION.
4863                get(String.valueOf(p.getPluginEntryDN()),
4864                    searchOperation.getConnectionID(),
4865                    searchOperation.getOperationID(),
4866                    String.valueOf(searchEntry.getDN()),
4867                    stackTraceToSingleLineString(e));
4868            logError(message);
4869    
4870            return PluginResult.IntermediateResponse.stopProcessing(false,
4871                DirectoryServer.getServerErrorResultCode(), message);
4872          }
4873    
4874          if (result == null)
4875          {
4876            Message message = ERR_PLUGIN_SEARCH_ENTRY_PLUGIN_RETURNED_NULL.
4877                get(String.valueOf(p.getPluginEntryDN()),
4878                    searchOperation.getConnectionID(),
4879                    searchOperation.getOperationID(),
4880                    String.valueOf(searchEntry.getDN()));
4881            logError(message);
4882    
4883            return PluginResult.IntermediateResponse.stopProcessing(false,
4884                DirectoryServer.getServerErrorResultCode(), message);
4885          }
4886          else if (! result.continuePluginProcessing())
4887          {
4888            return result;
4889          }
4890        }
4891    
4892        if (result == null)
4893        {
4894          // This should only happen if there were no search result entry plugins
4895          // registered, which is fine.
4896          result =
4897              PluginResult.IntermediateResponse.continueOperationProcessing(true);
4898        }
4899    
4900        return result;
4901      }
4902    
4903    
4904    
4905      /**
4906       * Invokes the set of search result reference plugins that have been
4907       * configured in the Directory Server.
4908       *
4909       * @param  searchOperation  The search operation for which to invoke the
4910       *                          search result reference plugins.
4911       * @param  searchReference  The search result reference to be processed.
4912       *
4913       * @return  The result of processing the search result reference plugins.
4914       */
4915      public PluginResult.IntermediateResponse invokeSearchResultReferencePlugins(
4916                                       LocalBackendSearchOperation searchOperation,
4917                                       SearchResultReference searchReference)
4918      {
4919        PluginResult.IntermediateResponse result = null;
4920    
4921        for (DirectoryServerPlugin p : searchResultReferencePlugins)
4922        {
4923          if (searchOperation.isInternalOperation() &&
4924              (! p.invokeForInternalOperations()))
4925          {
4926            continue;
4927          }
4928    
4929          try
4930          {
4931            result = p.processSearchReference(searchOperation, searchReference);
4932          }
4933          catch (Exception e)
4934          {
4935            if (debugEnabled())
4936            {
4937              TRACER.debugCaught(DebugLogLevel.ERROR, e);
4938            }
4939    
4940            Message message = ERR_PLUGIN_SEARCH_REFERENCE_PLUGIN_EXCEPTION.
4941                get(String.valueOf(p.getPluginEntryDN()),
4942                    searchOperation.getConnectionID(),
4943                    searchOperation.getOperationID(),
4944                    searchReference.getReferralURLString(),
4945                    stackTraceToSingleLineString(e));
4946            logError(message);
4947    
4948            return PluginResult.IntermediateResponse.stopProcessing(false,
4949                DirectoryServer.getServerErrorResultCode(), message);
4950          }
4951    
4952          if (result == null)
4953          {
4954            Message message = ERR_PLUGIN_SEARCH_REFERENCE_PLUGIN_RETURNED_NULL.
4955                get(String.valueOf(p.getPluginEntryDN()),
4956                    searchOperation.getConnectionID(),
4957                    searchOperation.getOperationID(),
4958                    searchReference.getReferralURLString());
4959            logError(message);
4960    
4961            return PluginResult.IntermediateResponse.stopProcessing(false,
4962                DirectoryServer.getServerErrorResultCode(), message);
4963          }
4964          else if (! result.continuePluginProcessing())
4965          {
4966            return result;
4967          }
4968        }
4969    
4970        if (result == null)
4971        {
4972          // This should only happen if there were no search result reference
4973          // plugins registered, which is fine.
4974          result =
4975              PluginResult.IntermediateResponse.continueOperationProcessing(true);
4976        }
4977    
4978        return result;
4979      }
4980    
4981    
4982    
4983      /**
4984       * Invokes the set of search result reference plugins that have been
4985       * configured in the Directory Server.
4986       *
4987       * @param  searchOperation  The search operation for which to invoke the
4988       *                          search result reference plugins.
4989       * @param  searchReference  The search result reference to be processed.
4990       *
4991       * @return  The result of processing the search result reference plugins.
4992       */
4993      public PluginResult.IntermediateResponse invokeSearchResultReferencePlugins(
4994          SearchReferenceSearchOperation searchOperation,
4995          SearchResultReference searchReference)
4996      {
4997        PluginResult.IntermediateResponse result = null;
4998    
4999        for (DirectoryServerPlugin p : searchResultReferencePlugins)
5000        {
5001          if (searchOperation.isInternalOperation() &&
5002              (! p.invokeForInternalOperations()))
5003          {
5004            continue;
5005          }
5006    
5007          try
5008          {
5009            result = p.processSearchReference(searchOperation, searchReference);
5010          }
5011          catch (Exception e)
5012          {
5013            if (debugEnabled())
5014            {
5015              TRACER.debugCaught(DebugLogLevel.ERROR, e);
5016            }
5017    
5018            Message message = ERR_PLUGIN_SEARCH_REFERENCE_PLUGIN_EXCEPTION.
5019                get(String.valueOf(p.getPluginEntryDN()),
5020                    searchOperation.getConnectionID(),
5021                    searchOperation.getOperationID(),
5022                    searchReference.getReferralURLString(),
5023                    stackTraceToSingleLineString(e));
5024            logError(message);
5025    
5026            return PluginResult.IntermediateResponse.stopProcessing(false,
5027                DirectoryServer.getServerErrorResultCode(), message);
5028          }
5029    
5030          if (result == null)
5031          {
5032            Message message = ERR_PLUGIN_SEARCH_REFERENCE_PLUGIN_RETURNED_NULL.
5033                get(String.valueOf(p.getPluginEntryDN()),
5034                    searchOperation.getConnectionID(),
5035                    searchOperation.getOperationID(),
5036                    searchReference.getReferralURLString());
5037            logError(message);
5038    
5039            return PluginResult.IntermediateResponse.stopProcessing(false,
5040                DirectoryServer.getServerErrorResultCode(), message);
5041          }
5042          else if (! result.continuePluginProcessing())
5043          {
5044            return result;
5045          }
5046        }
5047    
5048        if (result == null)
5049        {
5050          // This should only happen if there were no search result reference
5051          // plugins registered, which is fine.
5052          result =
5053              PluginResult.IntermediateResponse.continueOperationProcessing(true);
5054        }
5055    
5056        return result;
5057      }
5058    
5059    
5060    
5061      /**
5062       * Invokes the set of subordinate modify DN plugins that have been configured
5063       * in the Directory Server.
5064       *
5065       * @param  modifyDNOperation  The modify DN operation with which the
5066       *                            subordinate entry is associated.
5067       * @param  oldEntry           The subordinate entry prior to the move/rename
5068       *                            operation.
5069       * @param  newEntry           The subordinate entry after the move/rename
5070       *                            operation.
5071       * @param  modifications      A list into which any modifications made to the
5072       *                            target entry should be placed.
5073       *
5074       * @return  The result of processing the subordinate modify DN plugins.
5075       */
5076      public PluginResult.SubordinateModifyDN invokeSubordinateModifyDNPlugins(
5077                  SubordinateModifyDNOperation modifyDNOperation, Entry oldEntry,
5078                  Entry newEntry, List<Modification> modifications)
5079      {
5080        PluginResult.SubordinateModifyDN result = null;
5081    
5082        for (DirectoryServerPlugin p : subordinateModifyDNPlugins)
5083        {
5084          if (modifyDNOperation.isInternalOperation() &&
5085              (! p.invokeForInternalOperations()))
5086          {
5087            continue;
5088          }
5089    
5090          try
5091          {
5092            DirectoryServerPlugin<? extends PluginCfg> gp =
5093                 (DirectoryServerPlugin<? extends PluginCfg>) p;
5094            result = gp.processSubordinateModifyDN(modifyDNOperation, oldEntry,
5095                                                   newEntry, modifications);
5096          }
5097          catch (Exception e)
5098          {
5099            if (debugEnabled())
5100            {
5101              TRACER.debugCaught(DebugLogLevel.ERROR, e);
5102            }
5103    
5104            Message message =
5105                ERR_PLUGIN_SUBORDINATE_MODIFY_DN_PLUGIN_EXCEPTION.get(
5106                    String.valueOf(p.getPluginEntryDN()),
5107                    modifyDNOperation.getConnectionID(),
5108                    modifyDNOperation.getOperationID(),
5109                    stackTraceToSingleLineString(e));
5110            logError(message);
5111    
5112            return PluginResult.SubordinateModifyDN.stopProcessing(
5113                DirectoryServer.getServerErrorResultCode(), message);
5114          }
5115    
5116          if (result == null)
5117          {
5118            Message message =
5119                ERR_PLUGIN_SUBORDINATE_MODIFY_DN_PLUGIN_RETURNED_NULL.get(
5120                            String.valueOf(p.getPluginEntryDN()),
5121                            modifyDNOperation.getConnectionID(),
5122                            String.valueOf(modifyDNOperation.getOperationID()));
5123            logError(message);
5124    
5125            return PluginResult.SubordinateModifyDN.stopProcessing(
5126                DirectoryServer.getServerErrorResultCode(), message);
5127          }
5128          else if (! result.continuePluginProcessing())
5129          {
5130            return result;
5131          }
5132        }
5133    
5134        if (result == null)
5135        {
5136          // This should only happen if there were no subordinate modify DN plugins
5137          // registered, which is fine.
5138          result = PluginResult.SubordinateModifyDN.continueOperationProcessing();
5139        }
5140    
5141        return result;
5142      }
5143    
5144    
5145    
5146      /**
5147       * Invokes the set of intermediate response plugins that have been configured
5148       * in the Directory Server.
5149       *
5150       * @param  intermediateResponse  The intermediate response for which to invoke
5151       *                               the intermediate response plugins.
5152       *
5153       * @return  The result of processing the intermediate response plugins.
5154       */
5155      public PluginResult.IntermediateResponse
5156                  invokeIntermediateResponsePlugins(
5157                       IntermediateResponse intermediateResponse)
5158      {
5159        PluginResult.IntermediateResponse result = null;
5160        Operation operation = intermediateResponse.getOperation();
5161    
5162        for (DirectoryServerPlugin p : intermediateResponsePlugins)
5163        {
5164          try
5165          {
5166            result = p.processIntermediateResponse(intermediateResponse);
5167          }
5168          catch (Exception e)
5169          {
5170            if (debugEnabled())
5171            {
5172              TRACER.debugCaught(DebugLogLevel.ERROR, e);
5173            }
5174    
5175            Message message = ERR_PLUGIN_INTERMEDIATE_RESPONSE_PLUGIN_EXCEPTION.
5176                get(String.valueOf(p.getPluginEntryDN()),
5177                    operation.getConnectionID(), operation.getOperationID(),
5178                    stackTraceToSingleLineString(e));
5179            logError(message);
5180    
5181            return PluginResult.IntermediateResponse.stopProcessing
5182                (false, DirectoryServer.getServerErrorResultCode(), message);
5183          }
5184    
5185          if (result == null)
5186          {
5187            Message message = ERR_PLUGIN_INTERMEDIATE_RESPONSE_PLUGIN_RETURNED_NULL.
5188                get(String.valueOf(p.getPluginEntryDN()),
5189                    operation.getConnectionID(), operation.getOperationID());
5190            logError(message);
5191    
5192            return PluginResult.IntermediateResponse.stopProcessing
5193                (false, DirectoryServer.getServerErrorResultCode(), message);
5194          }
5195          else if (! result.continuePluginProcessing())
5196          {
5197            return result;
5198          }
5199        }
5200    
5201        if (result == null)
5202        {
5203          // This should only happen if there were no intermediate response plugins
5204          // registered, which is fine.
5205          result =
5206              PluginResult.IntermediateResponse.continueOperationProcessing(true);
5207        }
5208    
5209        return result;
5210      }
5211    
5212    
5213    
5214      /**
5215       * {@inheritDoc}
5216       */
5217      public boolean isConfigurationAddAcceptable(PluginCfg configuration,
5218                                                  List<Message> unacceptableReasons)
5219      {
5220        if (configuration.isEnabled())
5221        {
5222          // Create a set of plugin types for the plugin.
5223          HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
5224          for (PluginCfgDefn.PluginType pluginType :
5225               configuration.getPluginType())
5226          {
5227            pluginTypes.add(getPluginType(pluginType));
5228          }
5229    
5230          // Get the name of the class and make sure we can instantiate it as a
5231          // plugin.
5232          String className = configuration.getJavaClass();
5233          try
5234          {
5235            loadPlugin(className, pluginTypes, configuration, false);
5236          }
5237          catch (InitializationException ie)
5238          {
5239            unacceptableReasons.add(ie.getMessageObject());
5240            return false;
5241          }
5242        }
5243    
5244        // If we've gotten here, then it's fine.
5245        return true;
5246      }
5247    
5248    
5249    
5250      /**
5251       * {@inheritDoc}
5252       */
5253      public ConfigChangeResult applyConfigurationAdd(
5254                                     PluginCfg configuration)
5255      {
5256        ResultCode        resultCode          = ResultCode.SUCCESS;
5257        boolean           adminActionRequired = false;
5258        ArrayList<Message> messages            = new ArrayList<Message>();
5259    
5260        configuration.addChangeListener(this);
5261    
5262        if (! configuration.isEnabled())
5263        {
5264          return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5265        }
5266    
5267        // Create a set of plugin types for the plugin.
5268        HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
5269        for (PluginCfgDefn.PluginType pluginType :
5270             configuration.getPluginType())
5271        {
5272          pluginTypes.add(getPluginType(pluginType));
5273        }
5274    
5275        // Get the name of the class and make sure we can instantiate it as a
5276        // plugin.
5277        DirectoryServerPlugin<? extends PluginCfg> plugin = null;
5278        String className = configuration.getJavaClass();
5279        try
5280        {
5281          plugin = loadPlugin(className, pluginTypes, configuration, true);
5282        }
5283        catch (InitializationException ie)
5284        {
5285          if (resultCode == ResultCode.SUCCESS)
5286          {
5287            resultCode = DirectoryServer.getServerErrorResultCode();
5288          }
5289    
5290          messages.add(ie.getMessageObject());
5291        }
5292    
5293        if (resultCode == ResultCode.SUCCESS)
5294        {
5295          registerPlugin(plugin, configuration.dn(), pluginTypes);
5296        }
5297    
5298        return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5299      }
5300    
5301    
5302    
5303      /**
5304       * {@inheritDoc}
5305       */
5306      public boolean isConfigurationDeleteAcceptable(
5307                          PluginCfg configuration,
5308                          List<Message> unacceptableReasons)
5309      {
5310        // We will always allow plugins to be removed.
5311        return true;
5312      }
5313    
5314    
5315    
5316      /**
5317       * {@inheritDoc}
5318       */
5319      public ConfigChangeResult applyConfigurationDelete(
5320                                     PluginCfg configuration)
5321      {
5322        ResultCode        resultCode          = ResultCode.SUCCESS;
5323        boolean           adminActionRequired = false;
5324        ArrayList<Message> messages            = new ArrayList<Message>();
5325    
5326        deregisterPlugin(configuration.dn());
5327    
5328        return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5329      }
5330    
5331    
5332    
5333      /**
5334       * {@inheritDoc}
5335       */
5336      public boolean isConfigurationChangeAcceptable(
5337                          PluginCfg configuration,
5338                          List<Message> unacceptableReasons)
5339      {
5340        if (configuration.isEnabled())
5341        {
5342          // Create a set of plugin types for the plugin.
5343          HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
5344          for (PluginCfgDefn.PluginType pluginType :
5345               configuration.getPluginType())
5346          {
5347            pluginTypes.add(getPluginType(pluginType));
5348          }
5349    
5350          // Get the name of the class and make sure we can instantiate it as a
5351          // plugin.
5352          String className = configuration.getJavaClass();
5353          try
5354          {
5355            loadPlugin(className, pluginTypes, configuration, false);
5356          }
5357          catch (InitializationException ie)
5358          {
5359            unacceptableReasons.add(ie.getMessageObject());
5360            return false;
5361          }
5362        }
5363    
5364        // If we've gotten here, then it's fine.
5365        return true;
5366      }
5367    
5368    
5369    
5370      /**
5371       * {@inheritDoc}
5372       */
5373      public ConfigChangeResult applyConfigurationChange(
5374                                     PluginCfg configuration)
5375      {
5376        ResultCode        resultCode          = ResultCode.SUCCESS;
5377        boolean           adminActionRequired = false;
5378        ArrayList<Message> messages            = new ArrayList<Message>();
5379    
5380    
5381        // Get the existing plugin if it's already enabled.
5382        DirectoryServerPlugin existingPlugin =
5383             registeredPlugins.get(configuration.dn());
5384    
5385    
5386        // If the new configuration has the plugin disabled, then deregister it if
5387        // it is enabled, or do nothing if it's already disabled.
5388        if (! configuration.isEnabled())
5389        {
5390          if (existingPlugin != null)
5391          {
5392            deregisterPlugin(configuration.dn());
5393          }
5394    
5395          return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5396        }
5397    
5398    
5399        // Get the class for the identity mapper.  If the mapper is already enabled,
5400        // then we shouldn't do anything with it although if the class has changed
5401        // then we'll at least need to indicate that administrative action is
5402        // required.  If the mapper is disabled, then instantiate the class and
5403        // initialize and register it as an identity mapper.  Also, update the
5404        // plugin to indicate whether it should be invoked for internal operations.
5405        String className = configuration.getJavaClass();
5406        if (existingPlugin != null)
5407        {
5408          if (! className.equals(existingPlugin.getClass().getName()))
5409          {
5410            adminActionRequired = true;
5411          }
5412    
5413          existingPlugin.setInvokeForInternalOperations(
5414                              configuration.isInvokeForInternalOperations());
5415    
5416          return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5417        }
5418    
5419        // Create a set of plugin types for the plugin.
5420        HashSet<PluginType> pluginTypes = new HashSet<PluginType>();
5421        for (PluginCfgDefn.PluginType pluginType :
5422             configuration.getPluginType())
5423        {
5424          pluginTypes.add(getPluginType(pluginType));
5425        }
5426    
5427        DirectoryServerPlugin<? extends PluginCfg> plugin = null;
5428        try
5429        {
5430          plugin = loadPlugin(className, pluginTypes, configuration, true);
5431        }
5432        catch (InitializationException ie)
5433        {
5434          if (resultCode == ResultCode.SUCCESS)
5435          {
5436            resultCode = DirectoryServer.getServerErrorResultCode();
5437          }
5438    
5439          messages.add(ie.getMessageObject());
5440        }
5441    
5442        if (resultCode == ResultCode.SUCCESS)
5443        {
5444          registerPlugin(plugin, configuration.dn(), pluginTypes);
5445        }
5446    
5447        return new ConfigChangeResult(resultCode, adminActionRequired, messages);
5448      }
5449    
5450      private void registerSkippedPreOperationPlugins(int i,
5451                                                    DirectoryServerPlugin[] plugins,
5452                                                     PluginOperation operation)
5453      {
5454        ArrayList<DirectoryServerPlugin> skippedPlugins =
5455            new ArrayList<DirectoryServerPlugin>(plugins.length - i);
5456        for(int j = i; j < plugins.length; j++)
5457        {
5458          skippedPlugins.add(plugins[j]);
5459        }
5460        skippedPreOperationPlugins.put(operation, skippedPlugins);
5461      }
5462    
5463      private void registerSkippedPreOperationPlugin(DirectoryServerPlugin plugin,
5464                                                     PluginOperation operation)
5465      {
5466        ArrayList<DirectoryServerPlugin> existingList =
5467            skippedPreOperationPlugins.get(operation);
5468        if(existingList == null)
5469        {
5470          existingList = new ArrayList<DirectoryServerPlugin>();
5471        }
5472        existingList.add(plugin);
5473        skippedPreOperationPlugins.put(operation, existingList);
5474      }
5475    }
5476