From 95b6eab545532a8feaecd358e28631ccd3c00dc1 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 25 Apr 2013 09:00:37 +0000
Subject: [PATCH] OPENDJ-879 (CR-1603) Add HTTP access log

---
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml |   28 
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml       |   20 
 opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java                             |   20 
 opendj-sdk/opends/src/server/org/opends/server/loggers/AbstractLogger.java                       |  409 +++++++++++++
 opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java                         |  381 ++----------
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml  |   27 
 opendj-sdk/opends/src/server/org/opends/server/loggers/ErrorLogger.java                          |  339 +----------
 opendj-sdk/opends/src/server/org/opends/server/core/LoggerConfigManager.java                     |  163 ++--
 opendj-sdk/opends/src/admin/messages/LogPublisherCfgDefn.properties                              |    1 
 opendj-sdk/opends/src/server/org/opends/server/loggers/debug/DebugLogger.java                    |  349 +---------
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml  |   27 
 11 files changed, 703 insertions(+), 1,061 deletions(-)

diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml
index 2ff68ea..5dfaa18 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml
@@ -24,7 +24,7 @@
   !
   !
   !      Copyright 2007-2008 Sun Microsystems, Inc.
-  !      Portions copyright 2011 ForgeRock AS.
+  !      Portions copyright 2011-2013 ForgeRock AS
   ! -->
 <adm:managed-object name="access-log-publisher"
   plural-name="access-log-publishers"
@@ -59,25 +59,13 @@
       <ldap:rdn-sequence>cn=Filtering Criteria</ldap:rdn-sequence>
     </adm:profile>
   </adm:relation>
-  <adm:property name="java-class" mandatory="true">
-    <adm:synopsis>
-      The fully-qualified name of the Java class that provides the
-      <adm:user-friendly-name />
-      implementation.
-    </adm:synopsis>
-    <adm:syntax>
-      <adm:java-class>
-        <adm:instance-of>
-          org.opends.server.api.AccessLogPublisher
-        </adm:instance-of>
-      </adm:java-class>
-    </adm:syntax>
-    <adm:profile name="ldap">
-      <ldap:attribute>
-        <ldap:name>ds-cfg-java-class</ldap:name>
-      </ldap:attribute>
-    </adm:profile>
-  </adm:property>
+  <adm:property-override name="java-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>org.opends.server.api.AccessLogPublisher</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
   <adm:property name="filtering-policy">
     <adm:synopsis>
       Specifies how filtering criteria should be applied to log records. 
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml
index 4486b00..f406685 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml
@@ -24,6 +24,7 @@
   !
   !
   !      Copyright 2007-2008 Sun Microsystems, Inc.
+  !      Portions copyright 2013 ForgeRock AS
   ! -->
 <adm:managed-object name="debug-log-publisher"
   plural-name="debug-log-publishers"
@@ -62,25 +63,13 @@
       </cli:relation>
     </adm:profile>
   </adm:relation>
-  <adm:property name="java-class" mandatory="true">
-    <adm:synopsis>
-      The fully-qualified name of the Java class that provides the
-      <adm:user-friendly-name />
-      implementation.
-    </adm:synopsis>
-    <adm:syntax>
-      <adm:java-class>
-        <adm:instance-of>
-          org.opends.server.api.DebugLogPublisher
-        </adm:instance-of>
-      </adm:java-class>
-    </adm:syntax>
-    <adm:profile name="ldap">
-      <ldap:attribute>
-        <ldap:name>ds-cfg-java-class</ldap:name>
-      </ldap:attribute>
-    </adm:profile>
-  </adm:property>
+  <adm:property-override name="java-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>org.opends.server.api.DebugLogPublisher</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
   <adm:property name="default-debug-level" mandatory="true">
     <adm:synopsis>
       The lowest severity level of debug messages to log when none of
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
index 7688ade..d2a1c01 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
@@ -24,6 +24,7 @@
   !
   !
   !      Copyright 2007-2008 Sun Microsystems, Inc.
+  !      Portions copyright 2013 ForgeRock AS
   ! -->
 <adm:managed-object name="error-log-publisher"
   plural-name="error-log-publishers"
@@ -49,25 +50,13 @@
   <adm:profile name="cli">
     <cli:managed-object custom="true" />
   </adm:profile>
-  <adm:property name="java-class" mandatory="true">
-    <adm:synopsis>
-      The fully-qualified name of the Java class that provides the
-      <adm:user-friendly-name />
-      implementation.
-    </adm:synopsis>
-    <adm:syntax>
-      <adm:java-class>
-        <adm:instance-of>
-          org.opends.server.api.ErrorLogPublisher
-        </adm:instance-of>
-      </adm:java-class>
-    </adm:syntax>
-    <adm:profile name="ldap">
-      <ldap:attribute>
-        <ldap:name>ds-cfg-java-class</ldap:name>
-      </ldap:attribute>
-    </adm:profile>
-  </adm:property>
+  <adm:property-override name="java-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>org.opends.server.api.ErrorLogPublisher</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
   <adm:property name="default-severity" multi-valued="true">
     <adm:synopsis>
       Specifies the default severity levels for the logger.
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml
index 1d65a20..938e016 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml
@@ -24,6 +24,7 @@
   !
   !
   !      Copyright 2007-2008 Sun Microsystems, Inc.
+  !      Portions copyright 2013 ForgeRock AS
   ! -->
 <adm:managed-object name="log-publisher" plural-name="log-publishers"
   package="org.opends.server.admin.std" abstract="true"
@@ -56,4 +57,23 @@
       </ldap:attribute>
     </adm:profile>
   </adm:property>
+  <adm:property name="java-class" mandatory="true">
+    <adm:synopsis>
+      The fully-qualified name of the Java class that provides the
+      <adm:user-friendly-name />
+      implementation.
+    </adm:synopsis>
+    <adm:syntax>
+      <adm:java-class>
+        <adm:instance-of>
+          org.opends.server.api.LogPublisher
+        </adm:instance-of>
+      </adm:java-class>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-java-class</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
 </adm:managed-object>
diff --git a/opendj-sdk/opends/src/admin/messages/LogPublisherCfgDefn.properties b/opendj-sdk/opends/src/admin/messages/LogPublisherCfgDefn.properties
index 0ad75c9..bc4db58 100644
--- a/opendj-sdk/opends/src/admin/messages/LogPublisherCfgDefn.properties
+++ b/opendj-sdk/opends/src/admin/messages/LogPublisherCfgDefn.properties
@@ -2,3 +2,4 @@
 user-friendly-plural-name=Log Publishers
 synopsis=Log Publishers are responsible for distributing log messages from different loggers to a destination.
 property.enabled.synopsis=Indicates whether the Log Publisher is enabled for use.
+property.java-class.synopsis=The fully-qualified name of the Java class that provides the Log Publisher implementation.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/LoggerConfigManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/LoggerConfigManager.java
index a6c1a5d..1ef20fd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/LoggerConfigManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/LoggerConfigManager.java
@@ -23,27 +23,29 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions copyright 2013 ForgeRock AS
  */
 package org.opends.server.core;
-import org.opends.messages.Message;
 
-
-
-import java.util.*;
-
-import org.opends.server.config.ConfigException;
-import org.opends.server.types.*;
-
-import org.opends.server.loggers.debug.DebugLogger;
-import org.opends.server.loggers.ErrorLogger;
-import org.opends.server.loggers.AccessLogger;
 import static org.opends.messages.ConfigMessages.*;
 import static org.opends.server.loggers.ErrorLogger.*;
 
-import org.opends.server.admin.std.server.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.messages.Message;
 import org.opends.server.admin.server.ConfigurationAddListener;
 import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.server.*;
+import org.opends.server.config.ConfigException;
+import org.opends.server.loggers.AbstractLogger;
+import org.opends.server.loggers.AccessLogger;
+import org.opends.server.loggers.ErrorLogger;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
 
 
 /**
@@ -123,67 +125,77 @@
       logError(WARN_CONFIG_LOGGER_NO_ACTIVE_ERROR_LOGGERS.get());
     }
 
-    DebugLogger.getInstance().initializeDebugLogger(debugPublisherCfgs);
-    AccessLogger.getInstance().initializeAccessLogger(accessPublisherCfgs);
-    ErrorLogger.getInstance().initializeErrorLogger(errorPublisherCfgs);
+    DebugLogger.getInstance().initializeLogger(debugPublisherCfgs);
+    AccessLogger.getInstance().initializeLogger(accessPublisherCfgs);
+    ErrorLogger.getInstance().initializeLogger(errorPublisherCfgs);
+  }
+
+  /**
+   * Returns the logger instance corresponding to the provided config. If no
+   * logger corresponds to it, null will be returned and a message will be added
+   * to the provided messages list.
+   *
+   * @param config
+   *          the config for which to return the logger instance
+   * @param messages
+   *          where the error message will be output if no logger correspond to
+   *          the provided config.
+   * @return the logger corresponding to the provided config, null if no logger
+   *         corresponds.
+   */
+  private AbstractLogger getLoggerInstance(LogPublisherCfg config,
+      List<Message> messages)
+  {
+    if (config instanceof DebugLogPublisherCfg)
+    {
+      return DebugLogger.getInstance();
+    }
+    else if (config instanceof AccessLogPublisherCfg)
+    {
+      return AccessLogger.getInstance();
+    }
+    else if (config instanceof ErrorLogPublisherCfg)
+    {
+      return ErrorLogger.getInstance();
+    }
+    else
+    {
+      messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get(String
+          .valueOf(config.dn())));
+      return null;
+    }
   }
 
   /**
    * {@inheritDoc}
    */
+  @Override
   public boolean isConfigurationAddAcceptable(LogPublisherCfg config,
                                               List<Message> unacceptableReasons)
   {
-    if(config instanceof DebugLogPublisherCfg)
+    AbstractLogger instance = getLoggerInstance(config, unacceptableReasons);
+    if (instance != null)
     {
-      return DebugLogger.getInstance().isConfigurationAddAcceptable(
-          (DebugLogPublisherCfg)config, unacceptableReasons);
+      return instance.isConfigurationAddAcceptable(config, unacceptableReasons);
     }
-   else if(config instanceof AccessLogPublisherCfg)
-   {
-     return AccessLogger.getInstance().isConfigurationAddAcceptable(
-         (AccessLogPublisherCfg)config, unacceptableReasons);
-   }
-   else if(config instanceof ErrorLogPublisherCfg)
-   {
-     return ErrorLogger.getInstance().isConfigurationAddAcceptable(
-         (ErrorLogPublisherCfg)config, unacceptableReasons);
-   }
-    else
-    {
-
-      unacceptableReasons.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get(
-              String.valueOf(config.dn())));
-      return false;
-    }
+    return false;
   }
 
   /**
    * {@inheritDoc}
    */
+  @Override
   public ConfigChangeResult applyConfigurationAdd(LogPublisherCfg config)
   {
-    if(config instanceof DebugLogPublisherCfg)
+    List<Message> messages = new ArrayList<Message>(1);
+    AbstractLogger instance = getLoggerInstance(config, messages);
+    if (instance != null)
     {
-      return DebugLogger.getInstance().applyConfigurationAdd(
-          (DebugLogPublisherCfg)config);
+      return instance.applyConfigurationAdd(config);
     }
-   else if(config instanceof AccessLogPublisherCfg)
-   {
-     return AccessLogger.getInstance().applyConfigurationAdd(
-         (AccessLogPublisherCfg)config);
-   }
-   else if(config instanceof ErrorLogPublisherCfg)
-   {
-     return ErrorLogger.getInstance().applyConfigurationAdd(
-         (ErrorLogPublisherCfg)config);
-   }
     else
     {
-      ArrayList<Message> messages            = new ArrayList<Message>();
-      messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.
-              get(String.valueOf(config.dn())));
-      boolean           adminActionRequired = false;
+      boolean adminActionRequired = false;
       ResultCode resultCode = ResultCode.UNWILLING_TO_PERFORM;
       return new ConfigChangeResult(resultCode, adminActionRequired, messages);
     }
@@ -192,61 +204,36 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public boolean isConfigurationDeleteAcceptable(LogPublisherCfg config,
                                               List<Message> unacceptableReasons)
   {
-    if(config instanceof DebugLogPublisherCfg)
+    AbstractLogger instance = getLoggerInstance(config, unacceptableReasons);
+    if (instance != null)
     {
-      return DebugLogger.getInstance().isConfigurationDeleteAcceptable(
-          (DebugLogPublisherCfg)config, unacceptableReasons);
+      return instance.isConfigurationDeleteAcceptable(config,
+          unacceptableReasons);
     }
-   else if(config instanceof AccessLogPublisherCfg)
-   {
-     return AccessLogger.getInstance().isConfigurationDeleteAcceptable(
-         (AccessLogPublisherCfg)config, unacceptableReasons);
-   }
-   else if(config instanceof ErrorLogPublisherCfg)
-   {
-     return ErrorLogger.getInstance().isConfigurationDeleteAcceptable(
-         (ErrorLogPublisherCfg)config, unacceptableReasons);
-   }
-    else
-    {
-      unacceptableReasons.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get(
-              String.valueOf(config.dn())));
-      return false;
-    }
+    return false;
   }
 
   /**
    * {@inheritDoc}
    */
+  @Override
   public ConfigChangeResult applyConfigurationDelete(LogPublisherCfg config)
   {
-    if(config instanceof DebugLogPublisherCfg)
+    List<Message> messages = new ArrayList<Message>(1);
+    AbstractLogger instance = getLoggerInstance(config, messages);
+    if (instance != null)
     {
-      return DebugLogger.getInstance().applyConfigurationDelete(
-          (DebugLogPublisherCfg)config);
+      return instance.applyConfigurationDelete(config);
     }
-   else if(config instanceof AccessLogPublisherCfg)
-   {
-     return AccessLogger.getInstance().applyConfigurationDelete(
-         (AccessLogPublisherCfg)config);
-   }
-   else if(config instanceof ErrorLogPublisherCfg)
-   {
-     return ErrorLogger.getInstance().applyConfigurationDelete(
-         (ErrorLogPublisherCfg)config);
-   }
     else
     {
-      ArrayList<Message> messages            = new ArrayList<Message>();
-      messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get(
-              String.valueOf(config.dn())));
       boolean           adminActionRequired = false;
       ResultCode resultCode = ResultCode.UNWILLING_TO_PERFORM;
       return new ConfigChangeResult(resultCode, adminActionRequired, messages);
     }
   }
 }
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/AbstractLogger.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/AbstractLogger.java
new file mode 100644
index 0000000..c37005b
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/AbstractLogger.java
@@ -0,0 +1,409 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions copyright 2011-2013 ForgeRock AS.
+ */
+package org.opends.server.loggers;
+
+import static org.opends.messages.ConfigMessages.*;
+import static org.opends.server.util.StaticUtils.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.opends.messages.Message;
+import org.opends.messages.MessageDescriptor.Arg3;
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.LogPublisherCfg;
+import org.opends.server.api.LogPublisher;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.StaticUtils;
+
+/**
+ * This class defines the wrapper that will invoke all registered loggers for
+ * each type of request received or response sent. If no log publishers are
+ * registered, messages will be directed to standard out.
+ *
+ * @param <P>
+ *          The type of the LogPublisher corresponding to this logger
+ * @param <C>
+ *          The type of the LogPublisherCfg corresponding to this logger
+ */
+public abstract class AbstractLogger
+    <P extends LogPublisher<C>, C extends LogPublisherCfg>
+    implements ConfigurationAddListener<C>, ConfigurationDeleteListener<C>,
+    ConfigurationChangeListener<C>
+{
+
+  /**
+   * The storage designed to store log publishers. It is helpful in abstracting
+   * away the methods used to manage the collection.
+   *
+   * @param <P>
+   *          The concrete {@link LogPublisher} type
+   * @param <C>
+   *          The concrete {@link LogPublisherCfg} type
+   */
+  protected static class LoggerStorage<P extends LogPublisher<C>,
+      C extends LogPublisherCfg>
+  {
+    /**
+     * Defined as public to allow subclasses of {@link AbstractLogger} to
+     * instantiate it.
+     */
+    public LoggerStorage()
+    {
+      super();
+    }
+
+    /**
+     * The set of loggers that have been registered with the server. It will
+     * initially be empty.
+     */
+    private Collection<P> logPublishers = new CopyOnWriteArrayList<P>();
+
+
+    /**
+     * Add a log publisher to the logger.
+     *
+     * @param publisher
+     *          The log publisher to add.
+     */
+    public synchronized void addLogPublisher(P publisher)
+    {
+      logPublishers.add(publisher);
+    }
+
+    /**
+     * Remove a log publisher from the logger.
+     *
+     * @param publisher
+     *          The log publisher to remove.
+     * @return True if the log publisher is removed or false otherwise.
+     */
+    public synchronized boolean removeLogPublisher(P publisher)
+    {
+      boolean removed = logPublishers.remove(publisher);
+
+      if (removed)
+      {
+        publisher.close();
+      }
+
+      return removed;
+    }
+
+    /**
+     * Removes all existing log publishers from the logger.
+     */
+    public synchronized void removeAllLogPublishers()
+    {
+      StaticUtils.close((Collection) logPublishers);
+      logPublishers.clear();
+    }
+
+    /**
+     * Returns the logPublishers.
+     *
+     * @return the collection of {@link LogPublisher}s
+     */
+    public Collection<P> getLogPublishers()
+    {
+      return logPublishers;
+    }
+  }
+
+  /**
+   * Returns the logger storage for the current logger.
+   *
+   * @return the logger storage for the current logger
+   */
+  protected abstract LoggerStorage<P, C> getStorage();
+
+  /**
+   * Returns the java {@link ClassPropertyDefinition} for the current logger.
+   *
+   * @return the java {@link ClassPropertyDefinition} for the current logger.
+   */
+  protected abstract ClassPropertyDefinition getJavaClassPropertyDefinition();
+
+  private final Class<P> logPublisherClass;
+
+  private final Arg3<CharSequence, CharSequence, CharSequence>
+      invalidLoggerClassErrorMessage;
+
+  /**
+   * The constructor for this class.
+   *
+   * @param logPublisherClass
+   *          the log publisher class
+   * @param invalidLoggerClassErrorMessage
+   *          the error message to use if the logger class in invalid
+   */
+  public AbstractLogger(
+      final Class<P> logPublisherClass,
+      final Arg3<CharSequence, CharSequence, CharSequence>
+          invalidLoggerClassErrorMessage)
+  {
+    this.logPublisherClass = logPublisherClass;
+    this.invalidLoggerClassErrorMessage = invalidLoggerClassErrorMessage;
+  }
+
+  /**
+   * Initializes all the log publishers.
+   *
+   * @param configs The log publisher configurations.
+   * @throws ConfigException
+   *           If an unrecoverable problem arises in the process of
+   *           performing the initialization as a result of the server
+   *           configuration.
+   * @throws InitializationException
+   *           If a problem occurs during initialization that is not
+   *           related to the server configuration.
+   */
+  public void initializeLogger(List<C> configs)
+      throws ConfigException, InitializationException
+  {
+    for (C config : configs)
+    {
+      config.addChangeListener((ConfigurationChangeListener) this);
+
+      if(config.isEnabled())
+      {
+        getStorage().addLogPublisher(getLogPublisher(config));
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean isConfigurationAddAcceptable(C config,
+      List<Message> unacceptableReasons)
+  {
+    return !config.isEnabled() ||
+        isJavaClassAcceptable(config, unacceptableReasons);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean isConfigurationChangeAcceptable(C config,
+      List<Message> unacceptableReasons)
+  {
+    return !config.isEnabled() ||
+        isJavaClassAcceptable(config, unacceptableReasons);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ConfigChangeResult applyConfigurationAdd(C config)
+  {
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<Message> messages = new ArrayList<Message>();
+
+    config.addChangeListener((ConfigurationChangeListener) this);
+
+    if(config.isEnabled())
+    {
+      try
+      {
+        getStorage().addLogPublisher(getLogPublisher(config));
+      }
+      catch(ConfigException e)
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+        messages.add(e.getMessageObject());
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      }
+      catch (Exception e)
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+        messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
+                String.valueOf(config.dn().toString()),
+                stackTraceToSingleLineString(e)));
+        resultCode = DirectoryServer.getServerErrorResultCode();
+      }
+    }
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+  }
+
+  private void debugCaught(LogLevel error, Exception e)
+  {
+    if (DebugLogger.debugEnabled())
+    {
+      DebugLogger.getTracer().debugCaught(DebugLogLevel.ERROR, e);
+    }
+  }
+
+  private P findLogPublisher(DN dn)
+  {
+    Collection<P> logPublishers = getStorage().getLogPublishers();
+    for (P publisher : logPublishers)
+    {
+      if (publisher.getDN().equals(dn))
+      {
+        return publisher;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ConfigChangeResult applyConfigurationChange(C config)
+  {
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+    ArrayList<Message> messages = new ArrayList<Message>();
+
+    P logPublisher = findLogPublisher(config.dn());
+    if(logPublisher == null)
+    {
+      if(config.isEnabled())
+      {
+        // Needs to be added and enabled.
+        return applyConfigurationAdd(config);
+      }
+    }
+    else
+    {
+      if(config.isEnabled())
+      {
+        // The publisher is currently active, so we don't need to do anything.
+        // Changes to the class name cannot be
+        // applied dynamically, so if the class name did change then
+        // indicate that administrative action is required for that
+        // change to take effect.
+        String className = config.getJavaClass();
+        if(!className.equals(logPublisher.getClass().getName()))
+        {
+          adminActionRequired = true;
+        }
+      }
+      else
+      {
+        // The publisher is being disabled so shut down and remove.
+        getStorage().removeLogPublisher(logPublisher);
+      }
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean isConfigurationDeleteAcceptable(C config,
+      List<Message> unacceptableReasons)
+  {
+    return findLogPublisher(config.dn()) != null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ConfigChangeResult applyConfigurationDelete(C config)
+  {
+    // Default result code.
+    ResultCode resultCode = ResultCode.SUCCESS;
+    boolean adminActionRequired = false;
+
+    P logPublisher = findLogPublisher(config.dn());
+    if(logPublisher != null)
+    {
+      getStorage().removeLogPublisher(logPublisher);
+    }
+    else
+    {
+      resultCode = ResultCode.NO_SUCH_OBJECT;
+    }
+
+    return new ConfigChangeResult(resultCode, adminActionRequired);
+  }
+
+  private boolean isJavaClassAcceptable(C config,
+                                        List<Message> unacceptableReasons)
+  {
+    String className = config.getJavaClass();
+    ClassPropertyDefinition pd = getJavaClassPropertyDefinition();
+    try {
+      // Load the class and cast it to a LogPublisher.
+      P publisher = pd.loadClass(className, logPublisherClass).newInstance();
+      // The class is valid as far as we can tell.
+      return publisher.isConfigurationAcceptable(config, unacceptableReasons);
+    } catch (Exception e) {
+      Message message =
+          invalidLoggerClassErrorMessage.get(className, config.dn().toString(),
+              String.valueOf(e));
+      unacceptableReasons.add(message);
+      return false;
+    }
+  }
+
+  private P getLogPublisher(C config) throws ConfigException
+  {
+    String className = config.getJavaClass();
+    ClassPropertyDefinition pd = getJavaClassPropertyDefinition();
+    try {
+      // Load the class and cast it to a LogPublisher.
+      P logPublisher = pd.loadClass(className, logPublisherClass).newInstance();
+      logPublisher.initializeLogPublisher(config);
+      // The log publisher has been successfully initialized.
+      return logPublisher;
+    }
+    catch (Exception e)
+    {
+      Message message =
+          invalidLoggerClassErrorMessage.get(className, config.dn().toString(),
+              String.valueOf(e));
+      throw new ConfigException(message, e);
+    }
+  }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java
index dbd0dc5..28c085b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java
@@ -27,25 +27,16 @@
  */
 package org.opends.server.loggers;
 import static org.opends.messages.ConfigMessages.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.*;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Collection;
 
 import org.opends.messages.Message;
 import org.opends.server.admin.ClassPropertyDefinition;
-import org.opends.server.admin.server.ConfigurationAddListener;
-import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.std.meta.AccessLogPublisherCfgDefn;
 import org.opends.server.admin.std.server.AccessLogPublisherCfg;
 import org.opends.server.api.AccessLogPublisher;
 import org.opends.server.api.ClientConnection;
-import org.opends.server.config.ConfigException;
 import org.opends.server.core.*;
-import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.*;
 
 
@@ -53,25 +44,42 @@
  * This class defines the wrapper that will invoke all registered access loggers
  * for each type of request received or response sent.
  */
-public class AccessLogger implements
-    ConfigurationAddListener<AccessLogPublisherCfg>,
-    ConfigurationDeleteListener<AccessLogPublisherCfg>,
-    ConfigurationChangeListener<AccessLogPublisherCfg>
+public class AccessLogger extends AbstractLogger
+    <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg>
 {
-  /**
-   * The tracer object for the debug logger.
-   */
-  private static final DebugTracer TRACER = getTracer();
 
-  // The set of access loggers that have been registered with the server.  It
-  // will initially be empty.
-  private static CopyOnWriteArrayList<AccessLogPublisher<?>> accessPublishers =
-      new CopyOnWriteArrayList<AccessLogPublisher<?>>();
+  private static LoggerStorage
+      <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg>
+      loggerStorage = new LoggerStorage
+      <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg>();
 
-  // The singleton instance of this class for configuration purposes.
+  /** The singleton instance of this class for configuration purposes. */
   private static final AccessLogger instance = new AccessLogger();
 
+  /**
+   * The constructor for this class.
+   */
+  public AccessLogger()
+  {
+    super((Class) AccessLogPublisher.class,
+        ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS);
+  }
 
+  /** {@inheritDoc} */
+  @Override
+  protected ClassPropertyDefinition getJavaClassPropertyDefinition()
+  {
+    return AccessLogPublisherCfgDefn.getInstance()
+        .getJavaClassPropertyDefinition();
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  protected LoggerStorage<AccessLogPublisher<AccessLogPublisherCfg>,
+      AccessLogPublisherCfg> getStorage()
+  {
+    return loggerStorage;
+  }
 
   /**
    * Retrieve the singleton instance of this class.
@@ -89,9 +97,9 @@
    * @param publisher The access log publisher to add.
    */
   public synchronized static void addAccessLogPublisher(
-      AccessLogPublisher<?> publisher)
+      AccessLogPublisher publisher)
   {
-    accessPublishers.add(publisher);
+    loggerStorage.addLogPublisher(publisher);
   }
 
   /**
@@ -101,16 +109,9 @@
    * @return The publisher that was removed or null if it was not found.
    */
   public synchronized static boolean removeAccessLogPublisher(
-      AccessLogPublisher<?> publisher)
+      AccessLogPublisher<AccessLogPublisherCfg> publisher)
   {
-    boolean removed = accessPublishers.remove(publisher);
-
-    if(removed)
-    {
-      publisher.close();
-    }
-
-    return removed;
+    return loggerStorage.removeLogPublisher(publisher);
   }
 
   /**
@@ -118,274 +119,20 @@
    */
   public synchronized static void removeAllAccessLogPublishers()
   {
-    for(AccessLogPublisher<?> publisher : accessPublishers)
-    {
-      publisher.close();
-    }
-
-    accessPublishers.clear();
+    loggerStorage.removeAllLogPublishers();
   }
 
   /**
-   * Initializes all the access log publishers.
+   * Returns all the registered access log publishers.
    *
-   * @param configs The access log publisher configurations.
-   * @throws ConfigException
-   *           If an unrecoverable problem arises in the process of
-   *           performing the initialization as a result of the server
-   *           configuration.
-   * @throws InitializationException
-   *           If a problem occurs during initialization that is not
-   *           related to the server configuration.
+   * @return a Collection of {@link AccessLogPublisher} objects
    */
-  public void initializeAccessLogger(List<AccessLogPublisherCfg> configs)
-      throws ConfigException, InitializationException
+  private static Collection
+      <AccessLogPublisher<AccessLogPublisherCfg>> getAccessLogPublishers()
   {
-    for(AccessLogPublisherCfg config : configs)
-    {
-      config.addAccessChangeListener(this);
-
-      if(config.isEnabled())
-      {
-        AccessLogPublisher<?> AccessLogPublisher = getAccessPublisher(config);
-
-        addAccessLogPublisher(AccessLogPublisher);
-      }
-    }
+    return loggerStorage.getLogPublishers();
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationAddAcceptable(
-      AccessLogPublisherCfg config,
-      List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationChangeAcceptable(
-      AccessLogPublisherCfg config,
-      List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationAdd(AccessLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    config.addAccessChangeListener(this);
-
-    if(config.isEnabled())
-    {
-      try
-      {
-        AccessLogPublisher<?> AccessLogPublisher = getAccessPublisher(config);
-
-        addAccessLogPublisher(AccessLogPublisher);
-      }
-      catch(ConfigException e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-        messages.add(e.getMessageObject());
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-
-        messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
-            String.valueOf(config.dn().toString()),
-            stackTraceToSingleLineString(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationChange(
-      AccessLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    DN dn = config.dn();
-
-    AccessLogPublisher<?> accessLogPublisher = null;
-    for(AccessLogPublisher<?> publisher : accessPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        accessLogPublisher = publisher;
-        break;
-      }
-    }
-
-    if(accessLogPublisher == null)
-    {
-      if(config.isEnabled())
-      {
-        // Needs to be added and enabled.
-        return applyConfigurationAdd(config);
-      }
-    }
-    else
-    {
-      if(config.isEnabled())
-      {
-        // The publisher is currently active, so we don't need to do anything.
-        // Changes to the class name cannot be
-        // applied dynamically, so if the class name did change then
-        // indicate that administrative action is required for that
-        // change to take effect.
-        String className = config.getJavaClass();
-        if(!className.equals(accessLogPublisher.getClass().getName()))
-        {
-          adminActionRequired = true;
-        }
-      }
-      else
-      {
-        // The publisher is being disabled so shut down and remove.
-        removeAccessLogPublisher(accessLogPublisher);
-      }
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationDeleteAcceptable(
-      AccessLogPublisherCfg config,
-      List<Message> unacceptableReasons)
-  {
-    DN dn = config.dn();
-
-    AccessLogPublisher<?> accessLogPublisher = null;
-    for(AccessLogPublisher<?> publisher : accessPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        accessLogPublisher = publisher;
-        break;
-      }
-    }
-
-    return accessLogPublisher != null;
-
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationDelete(
-      AccessLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-
-    AccessLogPublisher<?> accessLogPublisher = null;
-    for(AccessLogPublisher<?> publisher : accessPublishers)
-    {
-      if(publisher.getDN().equals(config.dn()))
-      {
-        accessLogPublisher = publisher;
-        break;
-      }
-    }
-
-    if(accessLogPublisher != null)
-    {
-      removeAccessLogPublisher(accessLogPublisher);
-    }
-    else
-    {
-      resultCode = ResultCode.NO_SUCH_OBJECT;
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired);
-  }
-
-  @SuppressWarnings("unchecked")
-  private boolean isJavaClassAcceptable(AccessLogPublisherCfg config,
-                                        List<Message> unacceptableReasons)
-  {
-    String className = config.getJavaClass();
-    AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a AccessLogPublisher.
-      AccessLogPublisher<AccessLogPublisherCfg> publisher =
-          pd.loadClass(className, AccessLogPublisher.class).newInstance();
-      // The class is valid as far as we can tell.
-      return publisher.isConfigurationAcceptable(config, unacceptableReasons);
-    } catch (Exception e) {
-      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
-          className,
-          config.dn().toString(),
-          String.valueOf(e));
-      unacceptableReasons.add(message);
-      return false;
-    }
-  }
-
-  private AccessLogPublisher<?> getAccessPublisher(AccessLogPublisherCfg config)
-      throws ConfigException {
-    String className = config.getJavaClass();
-    AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a AccessLogPublisher.
-      AccessLogPublisher<AccessLogPublisherCfg> accessLogPublisher =
-          pd.loadClass(className, AccessLogPublisher.class).newInstance();
-      accessLogPublisher.initializeLogPublisher(config);
-      // The access publisher has been successfully initialized.
-      return accessLogPublisher;
-    }
-    catch (Exception e)
-    {
-      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
-          className, config.dn().toString(), String.valueOf(e));
-      throw new ConfigException(message, e);
-    }
-  }
-
-
-
 
   /**
    * Writes a message to the access logger with information about a new client
@@ -396,7 +143,7 @@
    */
   public static void logConnect(ClientConnection clientConnection)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logConnect(clientConnection);
     }
@@ -418,7 +165,7 @@
                                    DisconnectReason disconnectReason,
                                    Message message)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logDisconnect(clientConnection, disconnectReason, message);
     }
@@ -435,7 +182,7 @@
    */
   public static void logAbandonRequest(AbandonOperation abandonOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logAbandonRequest(abandonOperation);
     }
@@ -452,7 +199,7 @@
    */
   public static void logAbandonResult(AbandonOperation abandonOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logAbandonResult(abandonOperation);
     }
@@ -469,7 +216,7 @@
    */
   public static void logAddRequest(AddOperation addOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logAddRequest(addOperation);
     }
@@ -486,7 +233,7 @@
    */
   public static void logAddResponse(AddOperation addOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logAddResponse(addOperation);
     }
@@ -503,7 +250,7 @@
    */
   public static void logBindRequest(BindOperation bindOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logBindRequest(bindOperation);
     }
@@ -520,7 +267,7 @@
    */
   public static void logBindResponse(BindOperation bindOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logBindResponse(bindOperation);
     }
@@ -537,7 +284,7 @@
    */
   public static void logCompareRequest(CompareOperation compareOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logCompareRequest(compareOperation);
     }
@@ -554,7 +301,7 @@
    */
   public static void logCompareResponse(CompareOperation compareOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logCompareResponse(compareOperation);
     }
@@ -571,7 +318,7 @@
    */
   public static void logDeleteRequest(DeleteOperation deleteOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logDeleteRequest(deleteOperation);
     }
@@ -588,7 +335,7 @@
    */
   public static void logDeleteResponse(DeleteOperation deleteOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logDeleteResponse(deleteOperation);
     }
@@ -605,7 +352,7 @@
    */
   public static void logExtendedRequest(ExtendedOperation extendedOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logExtendedRequest(extendedOperation);
     }
@@ -622,7 +369,7 @@
    */
   public static void logExtendedResponse(ExtendedOperation extendedOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logExtendedResponse(extendedOperation);
     }
@@ -639,7 +386,7 @@
    */
   public static void logModifyRequest(ModifyOperation modifyOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logModifyRequest(modifyOperation);
     }
@@ -656,7 +403,7 @@
    */
   public static void logModifyResponse(ModifyOperation modifyOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logModifyResponse(modifyOperation);
     }
@@ -673,7 +420,7 @@
    */
   public static void logModifyDNRequest(ModifyDNOperation modifyDNOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logModifyDNRequest(modifyDNOperation);
     }
@@ -691,7 +438,7 @@
    */
   public static void logModifyDNResponse(ModifyDNOperation modifyDNOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logModifyDNResponse(modifyDNOperation);
     }
@@ -708,7 +455,7 @@
    */
   public static void logSearchRequest(SearchOperation searchOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logSearchRequest(searchOperation);
     }
@@ -728,7 +475,7 @@
   public static void logSearchResultEntry(SearchOperation searchOperation,
                                           SearchResultEntry searchEntry)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logSearchResultEntry(searchOperation, searchEntry);
     }
@@ -747,7 +494,7 @@
   public static void logSearchResultReference(SearchOperation searchOperation,
                           SearchResultReference searchReference)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logSearchResultReference(searchOperation, searchReference);
     }
@@ -764,7 +511,7 @@
    */
   public static void logSearchResultDone(SearchOperation searchOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logSearchResultDone(searchOperation);
     }
@@ -781,7 +528,7 @@
    */
   public static void logUnbind(UnbindOperation unbindOperation)
   {
-    for (AccessLogPublisher<?> publisher : accessPublishers)
+    for (AccessLogPublisher<?> publisher : getAccessLogPublishers())
     {
       publisher.logUnbind(unbindOperation);
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/ErrorLogger.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/ErrorLogger.java
index 25ca9ee..1db7e65 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/loggers/ErrorLogger.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/ErrorLogger.java
@@ -28,53 +28,30 @@
 package org.opends.server.loggers;
 
 import static org.opends.messages.ConfigMessages.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.*;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.opends.messages.Message;
 import org.opends.server.admin.ClassPropertyDefinition;
-import org.opends.server.admin.server.ConfigurationAddListener;
-import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.std.meta.ErrorLogPublisherCfgDefn;
 import org.opends.server.admin.std.server.ErrorLogPublisherCfg;
 import org.opends.server.api.DirectoryThread;
 import org.opends.server.api.ErrorLogPublisher;
 import org.opends.server.backends.task.Task;
-import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.ResultCode;
 
 /**
  * This class defines the wrapper that will invoke all registered error loggers
  * for each type of request received or response sent. If no error log
  * publishers are registered, messages will be directed to standard out.
  */
-public class ErrorLogger implements
-    ConfigurationAddListener<ErrorLogPublisherCfg>,
-    ConfigurationDeleteListener<ErrorLogPublisherCfg>,
-    ConfigurationChangeListener<ErrorLogPublisherCfg>
+public class ErrorLogger extends AbstractLogger
+    <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>
 {
-  /**
-   * The tracer object for the debug logger.
-   */
-  private static final DebugTracer TRACER = getTracer();
 
-  // The set of error loggers that have been registered with the server. It
-  // will initially be empty.
-  private static CopyOnWriteArrayList<ErrorLogPublisher> errorPublishers =
-      new CopyOnWriteArrayList<ErrorLogPublisher>();
+  private static LoggerStorage
+      <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>
+      loggerStorage = new LoggerStorage
+      <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>();
 
-  // The singleton instance of this class for configuration purposes.
+  /** The singleton instance of this class for configuration purposes. */
   private static final ErrorLogger instance = new ErrorLogger();
 
   /**
@@ -88,6 +65,31 @@
   }
 
   /**
+   * The constructor for this class.
+   */
+  public ErrorLogger()
+  {
+    super((Class) ErrorLogPublisher.class,
+        ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  protected ClassPropertyDefinition getJavaClassPropertyDefinition()
+  {
+    return ErrorLogPublisherCfgDefn.getInstance()
+        .getJavaClassPropertyDefinition();
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  protected LoggerStorage<ErrorLogPublisher<ErrorLogPublisherCfg>,
+      ErrorLogPublisherCfg> getStorage()
+  {
+    return loggerStorage;
+  }
+
+  /**
    * Add an error log publisher to the error logger.
    *
    * @param publisher The error log publisher to add.
@@ -95,7 +97,7 @@
   public synchronized static void addErrorLogPublisher(
       ErrorLogPublisher publisher)
   {
-    errorPublishers.add(publisher);
+    loggerStorage.addLogPublisher(publisher);
   }
 
   /**
@@ -107,14 +109,7 @@
   public synchronized static boolean removeErrorLogPublisher(
       ErrorLogPublisher publisher)
   {
-    boolean removed = errorPublishers.remove(publisher);
-
-    if(removed)
-    {
-      publisher.close();
-    }
-
-    return removed;
+    return loggerStorage.removeLogPublisher(publisher);
   }
 
   /**
@@ -122,278 +117,17 @@
    */
   public synchronized static void removeAllErrorLogPublishers()
   {
-    for(ErrorLogPublisher publisher : errorPublishers)
-    {
-      publisher.close();
-    }
-
-    errorPublishers.clear();
+    loggerStorage.removeAllLogPublishers();
   }
 
   /**
-   * Initializes all the error log publishers.
-   *
-   * @param configs The error log publisher configurations.
-   * @throws ConfigException
-   *           If an unrecoverable problem arises in the process of
-   *           performing the initialization as a result of the server
-   *           configuration.
-   * @throws InitializationException
-   *           If a problem occurs during initialization that is not
-   *           related to the server configuration.
-   */
-  public void initializeErrorLogger(List<ErrorLogPublisherCfg> configs)
-      throws ConfigException, InitializationException
-  {
-    for(ErrorLogPublisherCfg config : configs)
-    {
-      config.addErrorChangeListener(this);
-
-      if(config.isEnabled())
-      {
-        ErrorLogPublisher errorLogPublisher = getErrorPublisher(config);
-
-        addErrorLogPublisher(errorLogPublisher);
-      }
-    }
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationAddAcceptable(ErrorLogPublisherCfg config,
-                                              List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationChangeAcceptable(
-          ErrorLogPublisherCfg config,
-          List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationAdd(ErrorLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    config.addErrorChangeListener(this);
-
-    if(config.isEnabled())
-    {
-      try
-      {
-        ErrorLogPublisher errorLogPublisher = getErrorPublisher(config);
-
-        addErrorLogPublisher(errorLogPublisher);
-      }
-      catch(ConfigException e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-        messages.add(e.getMessageObject());
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-        messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
-                String.valueOf(config.dn().toString()),
-                stackTraceToSingleLineString(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationChange(
-      ErrorLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    DN dn = config.dn();
-
-    ErrorLogPublisher errorLogPublisher = null;
-    for(ErrorLogPublisher publisher : errorPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        errorLogPublisher = publisher;
-        break;
-      }
-    }
-
-    if(errorLogPublisher == null)
-    {
-      if(config.isEnabled())
-      {
-        // Needs to be added and enabled.
-        return applyConfigurationAdd(config);
-      }
-    }
-    else
-    {
-      if(config.isEnabled())
-      {
-        // The publisher is currently active, so we don't need to do anything.
-        // Changes to the class name cannot be
-        // applied dynamically, so if the class name did change then
-        // indicate that administrative action is required for that
-        // change to take effect.
-        String className = config.getJavaClass();
-        if(!className.equals(errorLogPublisher.getClass().getName()))
-        {
-          adminActionRequired = true;
-        }
-      }
-      else
-      {
-        // The publisher is being disabled so shut down and remove.
-        removeErrorLogPublisher(errorLogPublisher);
-      }
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationDeleteAcceptable(
-          ErrorLogPublisherCfg config,
-          List<Message> unacceptableReasons)
-  {
-    DN dn = config.dn();
-
-    ErrorLogPublisher errorLogPublisher = null;
-    for(ErrorLogPublisher publisher : errorPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        errorLogPublisher = publisher;
-        break;
-      }
-    }
-
-    return errorLogPublisher != null;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationDelete(
-      ErrorLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-
-    ErrorLogPublisher errorLogPublisher = null;
-    for(ErrorLogPublisher publisher : errorPublishers)
-    {
-      if(publisher.getDN().equals(config.dn()))
-      {
-        errorLogPublisher = publisher;
-        break;
-      }
-    }
-
-    if(errorLogPublisher != null)
-    {
-      removeErrorLogPublisher(errorLogPublisher);
-    }
-    else
-    {
-      resultCode = ResultCode.NO_SUCH_OBJECT;
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired);
-  }
-
-  private boolean isJavaClassAcceptable(ErrorLogPublisherCfg config,
-                                        List<Message> unacceptableReasons)
-  {
-    String className = config.getJavaClass();
-    ErrorLogPublisherCfgDefn d = ErrorLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a ErrorLogPublisher.
-      ErrorLogPublisher<ErrorLogPublisherCfg> publisher =
-          pd.loadClass(className, ErrorLogPublisher.class).newInstance();
-      // The class is valid as far as we can tell.
-      return publisher.isConfigurationAcceptable(config, unacceptableReasons);
-    } catch (Exception e) {
-      Message message = ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS.get(
-              className,
-              config.dn().toString(),
-              String.valueOf(e));
-      unacceptableReasons.add(message);
-      return false;
-    }
-  }
-
-  private ErrorLogPublisher getErrorPublisher(ErrorLogPublisherCfg config)
-      throws ConfigException {
-    String className = config.getJavaClass();
-    ErrorLogPublisherCfgDefn d = ErrorLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a ErrorLogPublisher.
-      ErrorLogPublisher<ErrorLogPublisherCfg> errorLogPublisher =
-          pd.loadClass(className, ErrorLogPublisher.class).newInstance();
-      errorLogPublisher.initializeLogPublisher(config);
-      // The error publisher has been successfully initialized.
-      return errorLogPublisher;
-    }
-    catch (Exception e)
-    {
-      Message message = ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS.get(
-          className, config.dn().toString(), String.valueOf(e));
-      throw new ConfigException(message, e);
-    }
-  }
-
-
-
-  /**
    * Writes a message to the error log using the provided information.
    *
    * @param  message   The message to be logged.
    */
   public static void logError(Message message)
   {
-    for (ErrorLogPublisher publisher : errorPublishers)
+    for (ErrorLogPublisher publisher : loggerStorage.getLogPublishers())
     {
       publisher.logError(message);
     }
@@ -409,4 +143,3 @@
     }
   }
 }
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/debug/DebugLogger.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/debug/DebugLogger.java
index dd3ddf8..ba22b11 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/loggers/debug/DebugLogger.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/debug/DebugLogger.java
@@ -26,30 +26,19 @@
  *      Portions Copyright 2013 ForgeRock AS
  */
 package org.opends.server.loggers.debug;
+
 import static org.opends.messages.ConfigMessages.*;
-import static org.opends.server.util.StaticUtils.*;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
 
-import org.opends.messages.Message;
 import org.opends.server.admin.ClassPropertyDefinition;
-import org.opends.server.admin.server.ConfigurationAddListener;
-import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.std.meta.DebugLogPublisherCfgDefn;
 import org.opends.server.admin.std.server.DebugLogPublisherCfg;
 import org.opends.server.api.DebugLogPublisher;
-import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.AbstractLogger;
 import org.opends.server.loggers.LogLevel;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
 import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.ResultCode;
 
 /**
  * A logger for debug and trace logging. DebugLogger provides a debugging
@@ -63,46 +52,71 @@
  *
  * DebugLogger is self-initializing.
  */
-public class DebugLogger implements
-    ConfigurationAddListener<DebugLogPublisherCfg>,
-    ConfigurationDeleteListener<DebugLogPublisherCfg>,
-    ConfigurationChangeListener<DebugLogPublisherCfg>
+public class DebugLogger extends AbstractLogger
+    <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg>
 {
-  //The default level to log constructor exectuions.
+  /** The default level to log constructor executions. */
   static final LogLevel DEFAULT_CONSTRUCTOR_LEVEL =
       DebugLogLevel.VERBOSE;
-  //The default level to log method entry and exit pointcuts.
+  /** The default level to log method entry and exit pointcuts. */
   static final LogLevel DEFAULT_ENTRY_EXIT_LEVEL =
       DebugLogLevel.VERBOSE;
-  //The default level to log method entry and exit pointcuts.
+  /** The default level to log method entry and exit pointcuts. */
   static final LogLevel DEFAULT_THROWN_LEVEL =
       DebugLogLevel.ERROR;
 
-  // The set of all DebugTracer instances.
-  private static ConcurrentHashMap<String, DebugTracer> classTracers =
+  /** The set of all DebugTracer instances. */
+  private static Map<String, DebugTracer> classTracers =
       new ConcurrentHashMap<String, DebugTracer>();
 
-  // The set of debug loggers that have been registered with the server.  It
-  // will initially be empty.
-  private static CopyOnWriteArrayList<DebugLogPublisher> debugPublishers =
-      new CopyOnWriteArrayList<DebugLogPublisher>();
-
-  // Trace methods will use this static boolean to determine if debug is
-  // enabled so to not incur the cost of calling debugPublishers.isEmtpty().
+  /**
+   * Trace methods will use this static boolean to determine if debug is enabled
+   * so to not incur the cost of calling debugPublishers.isEmpty().
+   */
   static boolean enabled = false;
 
-  // The singleton instance of this class for configuration purposes.
+  private static final LoggerStorage
+      <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg>
+      loggerStorage = new LoggerStorage
+      <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg>();
+
+  /** The singleton instance of this class for configuration purposes. */
   static final DebugLogger instance = new DebugLogger();
 
   /**
+   * The constructor for this class.
+   */
+  public DebugLogger()
+  {
+    super((Class) DebugLogPublisher.class,
+        ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  protected ClassPropertyDefinition getJavaClassPropertyDefinition()
+  {
+    return DebugLogPublisherCfgDefn.getInstance()
+        .getJavaClassPropertyDefinition();
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  protected LoggerStorage<DebugLogPublisher<DebugLogPublisherCfg>,
+      DebugLogPublisherCfg> getStorage()
+  {
+    return loggerStorage;
+  }
+
+  /**
    * Add an debug log publisher to the debug logger.
    *
-   * @param publisher The error log publisher to add.
+   * @param publisher The debug log publisher to add.
    */
   public synchronized static void addDebugLogPublisher(
       DebugLogPublisher publisher)
   {
-    debugPublishers.add(publisher);
+    loggerStorage.addLogPublisher(publisher);
 
     updateTracerSettings();
 
@@ -118,19 +132,11 @@
   public synchronized static boolean removeDebugLogPublisher(
       DebugLogPublisher publisher)
   {
-    boolean removed = debugPublishers.remove(publisher);
-
-    if(removed)
-    {
-      publisher.close();
-    }
+    boolean removed = loggerStorage.removeLogPublisher(publisher);
 
     updateTracerSettings();
 
-    if(debugPublishers.isEmpty())
-    {
-      enabled = false;
-    }
+    enabled = !loggerStorage.getLogPublishers().isEmpty();
 
     return removed;
   }
@@ -140,12 +146,7 @@
    */
   public synchronized static void removeAllDebugLogPublishers()
   {
-    for(DebugLogPublisher publisher : debugPublishers)
-    {
-      publisher.close();
-    }
-
-    debugPublishers.clear();
+    loggerStorage.removeAllLogPublishers();
 
     updateTracerSettings();
 
@@ -153,256 +154,13 @@
   }
 
   /**
-   * Initializes all the debug log publishers.
-   *
-   * @param  configs The debug log publisher configurations.
-   * @throws ConfigException
-   *           If an unrecoverable problem arises in the process of
-   *           performing the initialization as a result of the server
-   *           configuration.
-   * @throws InitializationException
-   *           If a problem occurs during initialization that is not
-   *           related to the server configuration.
-   */
-  public void initializeDebugLogger(List<DebugLogPublisherCfg> configs)
-      throws ConfigException, InitializationException
-  {
-    for(DebugLogPublisherCfg config : configs)
-    {
-      config.addDebugChangeListener(this);
-
-      if(config.isEnabled())
-      {
-        DebugLogPublisher debugLogPublisher = getDebugPublisher(config);
-
-        addDebugLogPublisher(debugLogPublisher);
-      }
-    }
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationAddAcceptable(DebugLogPublisherCfg config,
-                                              List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationChangeAcceptable(DebugLogPublisherCfg config,
-                                              List<Message> unacceptableReasons)
-  {
-    return !config.isEnabled() ||
-        isJavaClassAcceptable(config, unacceptableReasons);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationAdd(DebugLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    config.addDebugChangeListener(this);
-
-    if(config.isEnabled())
-    {
-      try
-      {
-        DebugLogPublisher debugLogPublisher =
-            getDebugPublisher(config);
-
-        addDebugLogPublisher(debugLogPublisher);
-      }
-      catch(ConfigException e)
-      {
-        messages.add(e.getMessageObject());
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-      catch (Exception e)
-      {
-
-        messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
-                String.valueOf(config.dn().toString()),
-                stackTraceToSingleLineString(e)));
-        resultCode = DirectoryServer.getServerErrorResultCode();
-      }
-    }
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult applyConfigurationChange(
-      DebugLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-    ArrayList<Message> messages = new ArrayList<Message>();
-
-    DN dn = config.dn();
-
-    DebugLogPublisher debugLogPublisher = null;
-    for(DebugLogPublisher publisher : debugPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        debugLogPublisher = publisher;
-      }
-    }
-
-    if(debugLogPublisher == null)
-    {
-      if(config.isEnabled())
-      {
-        // Needs to be added and enabled.
-        return applyConfigurationAdd(config);
-      }
-    }
-    else
-    {
-      if(config.isEnabled())
-      {
-        // The publisher is currently active, so we don't need to do anything.
-        // Changes to the class name cannot be
-        // applied dynamically, so if the class name did change then
-        // indicate that administrative action is required for that
-        // change to take effect.
-        String className = config.getJavaClass();
-        if(!className.equals(debugLogPublisher.getClass().getName()))
-        {
-          adminActionRequired = true;
-        }
-      }
-      else
-      {
-        // The publisher is being disabled so shut down and remove.
-        removeDebugLogPublisher(debugLogPublisher);
-      }
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean isConfigurationDeleteAcceptable(DebugLogPublisherCfg config,
-                                             List<Message> unacceptableReasons)
-  {
-    DN dn = config.dn();
-
-    DebugLogPublisher debugLogPublisher = null;
-    for(DebugLogPublisher publisher : debugPublishers)
-    {
-      if(publisher.getDN().equals(dn))
-      {
-        debugLogPublisher = publisher;
-      }
-    }
-
-    return debugLogPublisher != null;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ConfigChangeResult
-         applyConfigurationDelete(DebugLogPublisherCfg config)
-  {
-    // Default result code.
-    ResultCode resultCode = ResultCode.SUCCESS;
-    boolean adminActionRequired = false;
-
-    DebugLogPublisher debugLogPublisher = null;
-    for(DebugLogPublisher publisher : debugPublishers)
-    {
-      if(publisher.getDN().equals(config.dn()))
-      {
-        debugLogPublisher = publisher;
-      }
-    }
-
-    if(debugLogPublisher != null)
-    {
-      removeDebugLogPublisher(debugLogPublisher);
-    }
-    else
-    {
-      resultCode = ResultCode.NO_SUCH_OBJECT;
-    }
-
-    return new ConfigChangeResult(resultCode, adminActionRequired);
-  }
-
-  private boolean isJavaClassAcceptable(DebugLogPublisherCfg config,
-                                        List<Message> unacceptableReasons)
-  {
-    String className = config.getJavaClass();
-    DebugLogPublisherCfgDefn d = DebugLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a DebugLogPublisher.
-      DebugLogPublisher<DebugLogPublisherCfg> publisher =
-          pd.loadClass(className, DebugLogPublisher.class).newInstance();
-      // The class is valid as far as we can tell.
-      return publisher.isConfigurationAcceptable(config, unacceptableReasons);
-    } catch (Exception e) {
-      Message message = ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS.get(
-              className,
-              config.dn().toString(),
-              String.valueOf(e));
-      unacceptableReasons.add(message);
-      return false;
-    }
-  }
-
-  private DebugLogPublisher getDebugPublisher(DebugLogPublisherCfg config)
-      throws ConfigException {
-    String className = config.getJavaClass();
-    DebugLogPublisherCfgDefn d = DebugLogPublisherCfgDefn.getInstance();
-    ClassPropertyDefinition pd =
-        d.getJavaClassPropertyDefinition();
-    try {
-      // Load the class and cast it to a DebugLogPublisher.
-      DebugLogPublisher<DebugLogPublisherCfg> debugLogPublisher =
-          pd.loadClass(className, DebugLogPublisher.class).newInstance();
-      debugLogPublisher.initializeLogPublisher(config);
-      // The debug publisher has been successfully initialized.
-      return debugLogPublisher;
-    }
-    catch (Exception e)
-    {
-      Message message = ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS.get(
-          className, config.dn().toString(), String.valueOf(e));
-      throw new ConfigException(message, e);
-    }
-  }
-
-  /**
    * Update all debug tracers with the settings in the registered
    * publishers.
    */
   static void updateTracerSettings()
   {
-    DebugLogPublisher[] publishers =
-        debugPublishers.toArray(new DebugLogPublisher[0]);
+    DebugLogPublisher<DebugLogPublisherCfg>[] publishers =
+        loggerStorage.getLogPublishers().toArray(new DebugLogPublisher[0]);
 
     for(DebugTracer tracer : classTracers.values())
     {
@@ -439,7 +197,8 @@
   public static DebugTracer getTracer()
   {
     DebugTracer tracer =
-        new DebugTracer(debugPublishers.toArray(new DebugLogPublisher[0]));
+        new DebugTracer(loggerStorage.getLogPublishers().toArray(
+            new DebugLogPublisher[0]));
     classTracers.put(tracer.getTracedClassName(), tracer);
 
     return tracer;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java b/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
index 210a86e..1cb2556 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
@@ -51,6 +51,7 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Enumeration;
@@ -4622,6 +4623,25 @@
    */
   public static void close(Closeable... closeables)
   {
+    if (closeables == null)
+    {
+      return;
+    }
+    close(Arrays.asList(closeables));
+  }
+
+  /**
+   * Closes the provided {@link Closeable}'s ignoring any errors which occurred.
+   *
+   * @param closeables
+   *          The closeables to be closed, which may be <code>null</code>.
+   */
+  public static void close(Collection<Closeable> closeables)
+  {
+    if (closeables == null)
+    {
+      return;
+    }
     for (Closeable closeable : closeables)
     {
       if (closeable != null)

--
Gitblit v1.10.0