From e433824f46514e6ed863eb6b95c70038331c8c24 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 24 Nov 2015 12:49:54 +0000
Subject: [PATCH] OPENDJ-2260 OPENDJ-2271 Integration of common audit into the server

---
 opendj-server-legacy/src/main/java/org/opends/server/loggers/AccessLogger.java                                                       |    1 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessAuditFilter.java                            |  169 ++
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java                                         |   18 
 opendj-server-legacy/src/main/java/org/opends/server/core/ConnectionHandlerConfigManager.java                                        |    4 
 opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java                                                       |   11 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CsvFileAccessLogPublisher.java                                          |   63 
 opendj-server-legacy/resource/schema/02-config.ldif                                                                                  |   84 +
 opendj-server-legacy/src/main/java/org/opends/server/loggers/AbstractLogger.java                                                     |   71 
 opendj-server-legacy/src/messages/org/opends/messages/protocol.properties                                                            |    2 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/OpenDJAccessEventBuilder.java                                           |  267 +++
 opendj-server-legacy/resource/config/config.ldif                                                                                     |   37 
 opendj-server-legacy/pom.xml                                                                                                         |   18 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/JmxConnectionHandler.java                                         |    3 
 opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalAccessLogPublisherConfiguration.xml     |  100 +
 opendj-server-legacy/src/messages/org/opends/messages/config.properties                                                              |    6 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/internal/InternalConnectionHandler.java                               |    6 
 opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalHTTPAccessLogPublisherConfiguration.xml |   82 +
 opendj-server-legacy/src/main/java/org/opends/server/controls/TransactionIdControl.java                                              |  129 +
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditLogPublisher.java                                            |   44 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java                                            |    3 
 opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPConnectionHandler.java                                                  |   10 
 opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileAccessLogPublisherConfiguration.xml      |  348 +++++
 opendj-server-legacy/src/main/java/org/opends/server/core/ServerContext.java                                                         |    8 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditDependencyProvider.java                                      |   85 +
 opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileHTTPAccessLogPublisherConfiguration.xml  |  330 ++++
 opendj-server-legacy/src/main/java/org/opends/server/admin/AdministrationConnector.java                                              |   15 
 opendj-server-legacy/src/test/java/org/opends/server/protocols/internal/InternalConnectionHandlerTestCase.java                       |    6 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java                                      |  554 ++++++++
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java                                       |   10 
 opendj-server-legacy/src/main/resources/org/opends/server/loggers/audit-config.json                                                  |  402 +++++
 opendj-server-legacy/src/main/java/org/opends/server/api/ConnectionHandler.java                                                      |    7 
 opendj-server-legacy/src/main/java/org/opends/server/util/ServerConstants.java                                                       |    5 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/ExternalAccessLogPublisher.java                                         |   63 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessCheckEnabledFilter.java                     |   68 
 opendj-server-legacy/src/messages/org/opends/messages/logger.properties                                                              |   31 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java                                                        |  943 +++++++++++++
 opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPAccessLogger.java                                                   |    1 
 opendj-server-legacy/src/test/java/org/opends/server/protocols/ldap/LdapTestCase.java                                                |    5 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java                                       |    3 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditHTTPAccessLogPublisher.java                                  |  109 +
 40 files changed, 4,084 insertions(+), 37 deletions(-)

diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileAccessLogPublisherConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileAccessLogPublisherConfiguration.xml
new file mode 100644
index 0000000..70e1844
--- /dev/null
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileAccessLogPublisherConfiguration.xml
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ! CDDL HEADER START
+  !
+  ! The contents of this file are subject to the terms of the
+  ! Common Development and Distribution License, Version 1.0 only
+  ! (the "License").  You may not use this file except in compliance
+  ! with the License.
+  !
+  ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+  ! or http://forgerock.org/license/CDDLv1.0.html.
+  ! 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 legal-notices/CDDLv1_0.txt.
+  ! 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 2015 ForgeRock AS.
+  ! -->
+<adm:managed-object name="csv-file-access-log-publisher"
+  plural-name="csv-file-access-log-publishers"
+  package="org.forgerock.opendj.server.config" extends="access-log-publisher"
+  xmlns:adm="http://opendj.forgerock.org/admin"
+  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
+  <adm:synopsis>
+    <adm:user-friendly-plural-name />
+    publish access messages to CSV files.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:name>ds-cfg-csv-file-access-log-publisher</ldap:name>
+      <ldap:superior>ds-cfg-access-log-publisher</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property-override name="java-class" advanced="true">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.loggers.CommonAuditAccessLogPublisher
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+  <adm:property name="log-directory" mandatory="true">
+    <adm:synopsis>
+      The directory to use for the log files generated by the
+      <adm:user-friendly-name />.
+      The path to the directory is relative to the server root.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:component-restart />
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>logs</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>DIRECTORY</adm:usage>
+          <adm:synopsis>
+            A path to an existing directory that is readable and writable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-log-directory</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="asynchronous" mandatory="true" advanced="true">
+    <adm:synopsis>
+      Indicates whether the
+      <adm:user-friendly-name />
+      will publish records asynchronously.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>true</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-asynchronous</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="auto-flush" advanced="true">
+    <adm:synopsis>
+      Specifies whether to flush the writer after every log record.
+    </adm:synopsis>
+    <adm:description>
+      If the asynchronous writes option is used, the writer is
+      flushed after all the log records in the queue are written.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>true</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-auto-flush</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="rotation-policy" multi-valued="true">
+    <adm:synopsis>
+      The rotation policy to use for the
+      <adm:user-friendly-name />
+      .
+    </adm:synopsis>
+    <adm:description>
+      When multiple policies are used, rotation will occur if any
+      policy's conditions are met.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          No rotation policy is used and log rotation will not occur.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:aggregation parent-path="/"
+        relation-name="log-rotation-policy" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-rotation-policy</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="retention-policy" multi-valued="true">
+    <adm:synopsis>
+      The retention policy to use for the
+      <adm:user-friendly-name />
+      .
+    </adm:synopsis>
+    <adm:description>
+      When multiple policies are used, log files are cleaned when
+      any of the policy's conditions are met.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          No retention policy is used and log files are never cleaned.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:aggregation parent-path="/"
+        relation-name="log-retention-policy" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-retention-policy</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="log-control-oids">
+    <adm:synopsis>
+      Specifies whether control OIDs will be included in operation log records.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>false</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-log-control-oids</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="tamper-evident">
+    <adm:synopsis>
+      Specifies whether the log should be signed in order to detect tampering.
+    </adm:synopsis>
+    <adm:description>
+      Every log record will be signed, making it possible to verify that the log has not been tampered with.
+      This feature has a significative impact on performance of the server.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>false</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-tamper-evident</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="signature-time-interval" advanced="true">
+    <adm:synopsis>
+      Specifies the interval at which to sign the log file when the tamper-evident option
+      is enabled.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>3s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="ms" lower-limit="1" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-signature-time-interval</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="key-store-file">
+    <adm:synopsis>
+      Specifies the path to the file that contains the private key
+      information. This may be an absolute path, or a path that is
+      relative to the <adm:product-name /> instance root.
+    </adm:synopsis>
+    <adm:description>
+      Changes to this property will take effect the next
+      time that the key store is accessed.
+    </adm:description>
+    <adm:default-behavior>
+        <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+        <adm:pattern>
+         <adm:regex>.*</adm:regex>
+         <adm:usage>FILE</adm:usage>
+          <adm:synopsis>
+            A path to an existing file that is readable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string> 
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-key-store-file</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property-reference name="key-store-pin-file" />
+  <adm:property name="csv-quote-char" advanced="true">
+    <adm:synopsis>
+      The character to append and prepend to a CSV field when writing in CSV format.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>\"</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>QUOTE CHARACTER</adm:usage>
+          <adm:synopsis>
+            The quote character to use when writting in CSV format.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-quote-char</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="csv-delimiter-char">
+    <adm:synopsis>
+      The delimiter character to use when writing in CSV format.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>,</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>DELIMITER CHARACTER</adm:usage>
+          <adm:synopsis>
+            The delimiter character to use when writing in CSV format.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-delimiter-char</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="csv-eol-symbols" advanced="true">
+    <adm:synopsis>
+      The string that marks the end of a line.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          Use the platform specific end of line character sequence.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>STRING</adm:usage>
+          <adm:synopsis>
+            The string that marks the end of a line.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-eol-symbols</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileHTTPAccessLogPublisherConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileHTTPAccessLogPublisherConfiguration.xml
new file mode 100644
index 0000000..b095c33
--- /dev/null
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CsvFileHTTPAccessLogPublisherConfiguration.xml
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ! CDDL HEADER START
+  !
+  ! The contents of this file are subject to the terms of the
+  ! Common Development and Distribution License, Version 1.0 only
+  ! (the "License").  You may not use this file except in compliance
+  ! with the License.
+  !
+  ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+  ! or http://forgerock.org/license/CDDLv1.0.html.
+  ! 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 legal-notices/CDDLv1_0.txt.
+  ! 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 2015 ForgeRock AS.
+  ! -->
+<adm:managed-object name="csv-file-http-access-log-publisher"
+  plural-name="csv-file-http-access-log-publishers"
+  package="org.forgerock.opendj.server.config" extends="http-access-log-publisher"
+  xmlns:adm="http://opendj.forgerock.org/admin"
+  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
+  <adm:synopsis>
+    <adm:user-friendly-plural-name />
+    publish HTTP access messages to CSV files.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:name>ds-cfg-csv-file-http-access-log-publisher</ldap:name>
+      <ldap:superior>ds-cfg-http-access-log-publisher</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property-override name="java-class" advanced="true">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.loggers.CommonAuditHTTPAccessLogPublisher
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+  <adm:property name="log-directory" mandatory="true">
+    <adm:synopsis>
+      The directory to use for the log files generated by the
+      <adm:user-friendly-name />.
+      The path to the directory is relative to the server root.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:component-restart />
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>logs</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>DIRECTORY</adm:usage>
+          <adm:synopsis>
+            A path to an existing directory that is readable and writable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-log-directory</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="asynchronous" mandatory="true" advanced="true">
+    <adm:synopsis>
+      Indicates whether the
+      <adm:user-friendly-name />
+      will publish records asynchronously.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>true</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-asynchronous</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="auto-flush" advanced="true">
+    <adm:synopsis>
+      Specifies whether to flush the writer after every log record.
+    </adm:synopsis>
+    <adm:description>
+      If the asynchronous writes option is used, the writer is
+      flushed after all the log records in the queue are written.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>true</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-auto-flush</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="rotation-policy" multi-valued="true">
+    <adm:synopsis>
+      The rotation policy to use for the
+      <adm:user-friendly-name />
+      .
+    </adm:synopsis>
+    <adm:description>
+      When multiple policies are used, rotation will occur if any
+      policy's conditions are met.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          No rotation policy is used and log rotation will not occur.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:aggregation parent-path="/"
+        relation-name="log-rotation-policy" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-rotation-policy</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="retention-policy" multi-valued="true">
+    <adm:synopsis>
+      The retention policy to use for the
+      <adm:user-friendly-name />
+      .
+    </adm:synopsis>
+    <adm:description>
+      When multiple policies are used, log files are cleaned when
+      any of the policy's conditions are met.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          No retention policy is used and log files are never cleaned.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:aggregation parent-path="/"
+        relation-name="log-retention-policy" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-retention-policy</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="tamper-evident">
+    <adm:synopsis>
+      Specifies whether the log should be signed in order to detect tampering.
+    </adm:synopsis>
+    <adm:description>
+      Every log record will be signed, making it possible to verify that the log has not been tampered with.
+      This feature has a significative impact on performance of the server.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>false</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-tamper-evident</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="signature-time-interval" advanced="true">
+    <adm:synopsis>
+      Specifies the interval at which to sign the log file when secure option
+      is enabled.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>3s</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:duration base-unit="ms" lower-limit="1" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-signature-time-interval</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="key-store-file">
+    <adm:synopsis>
+      Specifies the path to the file that contains the private key
+      information. This may be an absolute path, or a path that is
+      relative to the <adm:product-name /> instance root.
+    </adm:synopsis>
+    <adm:description>
+      Changes to this property will take effect the next
+      time that the key store is accessed.
+    </adm:description>
+    <adm:default-behavior>
+        <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+        <adm:pattern>
+         <adm:regex>.*</adm:regex>
+         <adm:usage>FILE</adm:usage>
+          <adm:synopsis>
+            A path to an existing file that is readable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string> 
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-key-store-file</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property-reference name="key-store-pin-file" />
+  <adm:property name="csv-quote-char" advanced="true">
+    <adm:synopsis>
+      The character to append and prepend to a CSV field when writing in CSV format.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>\"</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>QUOTE CHARACTER</adm:usage>
+          <adm:synopsis>
+            The quote character to use when writing in CSV format.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-quote-char</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="csv-delimiter-char">
+    <adm:synopsis>
+      The delimiter character to use when writing in CSV format.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>,</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>DELIMITER CHARACTER</adm:usage>
+          <adm:synopsis>
+            The delimiter character to use when writing in CSV format.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-delimiter-char</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="csv-eol-symbols" advanced="true">
+    <adm:synopsis>
+      The string that marks the end of a line.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:alias>
+        <adm:synopsis>
+          Use the platform specific end of line character sequence.
+        </adm:synopsis>
+      </adm:alias>
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>EOL SYMBOLS</adm:usage>
+          <adm:synopsis>
+            The string that marks the end of a line.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-csv-eol-symbols</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalAccessLogPublisherConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalAccessLogPublisherConfiguration.xml
new file mode 100644
index 0000000..fa2ff14
--- /dev/null
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalAccessLogPublisherConfiguration.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ! CDDL HEADER START
+  !
+  ! The contents of this file are subject to the terms of the
+  ! Common Development and Distribution License, Version 1.0 only
+  ! (the "License").  You may not use this file except in compliance
+  ! with the License.
+  !
+  ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+  ! or http://forgerock.org/license/CDDLv1.0.html.
+  ! 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 legal-notices/CDDLv1_0.txt.
+  ! 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 2015 ForgeRock AS.
+  ! -->
+<adm:managed-object name="external-access-log-publisher"
+  plural-name="external-access-log-publishers"
+  package="org.forgerock.opendj.server.config" extends="access-log-publisher"
+  xmlns:adm="http://opendj.forgerock.org/admin"
+  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
+  <adm:synopsis>
+    <adm:user-friendly-plural-name />
+    publish access messages to an external handler.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:name>ds-cfg-external-access-log-publisher</ldap:name>
+      <ldap:superior>ds-cfg-access-log-publisher</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property-override name="java-class" advanced="true">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.loggers.CommonAuditAccessLogPublisher
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+  <adm:property name="config-file" mandatory="true">
+    <adm:synopsis>
+      The JSON configuration file that defines the
+      <adm:user-friendly-name />. 
+      The content of the JSON configuration file depends on
+      the type of external audit event handler.
+      The path to the file is relative to the server root.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:component-restart />
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+        <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>FILE</adm:usage>
+          <adm:synopsis>
+            A path to an existing file that is readable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-config-file</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="log-control-oids">
+    <adm:synopsis>
+      Specifies whether control OIDs will be included in operation log records.
+    </adm:synopsis>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>false</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:boolean />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-log-control-oids</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalHTTPAccessLogPublisherConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalHTTPAccessLogPublisherConfiguration.xml
new file mode 100644
index 0000000..268bca9
--- /dev/null
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ExternalHTTPAccessLogPublisherConfiguration.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ! CDDL HEADER START
+  !
+  ! The contents of this file are subject to the terms of the
+  ! Common Development and Distribution License, Version 1.0 only
+  ! (the "License").  You may not use this file except in compliance
+  ! with the License.
+  !
+  ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+  ! or http://forgerock.org/license/CDDLv1.0.html.
+  ! 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 legal-notices/CDDLv1_0.txt.
+  ! 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 2015 ForgeRock AS.
+  ! -->
+<adm:managed-object name="external-http-access-log-publisher"
+  plural-name="external-http-access-log-publishers"
+  package="org.forgerock.opendj.server.config" extends="http-access-log-publisher"
+  xmlns:adm="http://opendj.forgerock.org/admin"
+  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
+  <adm:synopsis>
+    <adm:user-friendly-plural-name />
+    publish HTTP access messages to an external handler.
+  </adm:synopsis>
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:name>ds-cfg-external-http-access-log-publisher</ldap:name>
+      <ldap:superior>ds-cfg-http-access-log-publisher</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+  <adm:property-override name="java-class" advanced="true">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.loggers.CommonAuditHTTPAccessLogPublisher
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+  <adm:property name="config-file" mandatory="true">
+    <adm:synopsis>
+      The JSON configuration file that defines the
+      <adm:user-friendly-name />. 
+      The content of the JSON configuration file depends on
+      the type of external audit event handler.
+      The path to the file is relative to the server root.
+    </adm:synopsis>
+    <adm:requires-admin-action>
+      <adm:component-restart />
+    </adm:requires-admin-action>
+    <adm:default-behavior>
+        <adm:undefined />
+    </adm:default-behavior>
+    <adm:syntax>
+     <adm:string>
+       <adm:pattern>
+        <adm:regex>.*</adm:regex>
+        <adm:usage>FILE</adm:usage>
+          <adm:synopsis>
+            A path to an existing file that is readable by the server.
+          </adm:synopsis>
+        </adm:pattern>
+      </adm:string>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-config-file</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+</adm:managed-object>
diff --git a/opendj-server-legacy/pom.xml b/opendj-server-legacy/pom.xml
index 30e7813..8575a65 100644
--- a/opendj-server-legacy/pom.xml
+++ b/opendj-server-legacy/pom.xml
@@ -125,6 +125,11 @@
 
     <dependency>
       <groupId>org.forgerock.commons</groupId>
+      <artifactId>forgerock-util</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.forgerock.commons</groupId>
       <artifactId>json-resource</artifactId>
     </dependency>
 
@@ -142,6 +147,19 @@
       <groupId>org.forgerock.http</groupId>
       <artifactId>chf-http-servlet</artifactId>
     </dependency>
+ 
+    <dependency>
+      <groupId>org.forgerock.commons</groupId>
+      <artifactId>forgerock-audit-core</artifactId>
+    </dependency>  
+    <dependency>
+      <groupId>org.forgerock.commons</groupId>
+      <artifactId>forgerock-audit-handler-csv</artifactId>
+    </dependency>  
+    <dependency>
+      <groupId>org.forgerock.commons</groupId>
+      <artifactId>forgerock-audit-json</artifactId>
+    </dependency>  
 
     <!-- servlet and mail -->
     <dependency>
diff --git a/opendj-server-legacy/resource/config/config.ldif b/opendj-server-legacy/resource/config/config.ldif
index fe9b509..1fca49c 100644
--- a/opendj-server-legacy/resource/config/config.ldif
+++ b/opendj-server-legacy/resource/config/config.ldif
@@ -605,6 +605,26 @@
 ds-cfg-rotation-policy: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
 ds-cfg-retention-policy: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
 
+dn: cn=Common Audit Csv File Access Logger,cn=Loggers,cn=config
+objectClass: top
+objectClass: ds-cfg-log-publisher
+objectClass: ds-cfg-access-log-publisher
+objectClass: ds-cfg-csv-file-access-log-publisher
+cn: Csv File Access Logger
+ds-cfg-java-class: org.opends.server.loggers.CsvFileAccessLogPublisher
+ds-cfg-enabled: false
+ds-cfg-log-directory: logs
+ds-cfg-suppress-internal-operations: true
+ds-cfg-suppress-synchronization-operations: false
+ds-cfg-log-control-oids: false
+ds-cfg-asynchronous: true
+ds-cfg-rotation-policy: cn=24 Hours Time Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-rotation-policy: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-retention-policy: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
+ds-cfg-tamper-evident: false
+ds-cfg-key-store-file: config/audit-keystore
+ds-cfg-key-store-pin-file: config/audit-keystore.pin
+
 dn: cn=File-Based HTTP Access Logger,cn=Loggers,cn=config
 objectClass: top
 objectClass: ds-cfg-log-publisher
@@ -620,6 +640,23 @@
 ds-cfg-rotation-policy: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
 ds-cfg-retention-policy: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
 
+dn: cn=Common Audit Csv File HTTP Access Logger,cn=Loggers,cn=config
+objectClass: top
+objectClass: ds-cfg-log-publisher
+objectClass: ds-cfg-http-access-log-publisher
+objectClass: ds-cfg-csv-file-http-access-log-publisher
+cn: Csv File HTTP Access Logger
+ds-cfg-java-class: org.opends.server.loggers.CommonAuditHTTPAccessLogPublisher
+ds-cfg-enabled: false
+ds-cfg-log-directory: logs
+ds-cfg-asynchronous: true
+ds-cfg-rotation-policy: cn=24 Hours Time Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-rotation-policy: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-retention-policy: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
+ds-cfg-tamper-evident: false
+ds-cfg-key-store-file: config/audit-keystore
+ds-cfg-key-store-pin-file: config/audit-keystore.pin
+
 dn: cn=File-Based Audit Logger,cn=Loggers,cn=config
 objectClass: top
 objectClass: ds-cfg-log-publisher
diff --git a/opendj-server-legacy/resource/schema/02-config.ldif b/opendj-server-legacy/resource/schema/02-config.ldif
index 867d159..e04673b 100644
--- a/opendj-server-legacy/resource/schema/02-config.ldif
+++ b/opendj-server-legacy/resource/schema/02-config.ldif
@@ -3806,6 +3806,41 @@
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
   SINGLE-VALUE
   X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.149
+  NAME 'ds-cfg-signature-time-interval'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.150
+  NAME 'ds-cfg-log-directory'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.151
+  NAME 'ds-cfg-csv-quote-char'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.152
+  NAME 'ds-cfg-csv-delimiter-char'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDJ Directory Server' )  
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.153
+  NAME 'ds-cfg-csv-eol-symbols'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.154
+  NAME 'ds-cfg-tamper-evident'
+  EQUALITY booleanMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDJ Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler'
   SUP top
@@ -5844,8 +5879,55 @@
 objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.27
   NAME 'ds-task-reset-change-number'
   SUP ds-task
-  STRUCTURAL
   MUST ( ds-task-reset-change-number-to $
         ds-task-reset-change-number-base-dn $
         ds-task-reset-change-number-csn )
   X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.28
+  NAME 'ds-cfg-csv-file-access-log-publisher'
+  SUP ds-cfg-access-log-publisher
+  STRUCTURAL
+  MUST ( ds-cfg-log-directory )
+  MAY ( ds-cfg-log-control-oids $
+        ds-cfg-csv-quote-char $
+        ds-cfg-csv-delimiter-char $
+        ds-cfg-csv-eol-symbols $
+        ds-cfg-auto-flush $
+        ds-cfg-asynchronous $
+        ds-cfg-rotation-policy $
+        ds-cfg-retention-policy $
+        ds-cfg-tamper-evident $
+        ds-cfg-signature-time-interval $
+        ds-cfg-key-store-file $
+        ds-cfg-key-store-pin-file )
+  X-ORIGIN 'OpenDJ Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.29
+  NAME 'ds-cfg-csv-file-http-access-log-publisher'
+  SUP ds-cfg-http-access-log-publisher
+  STRUCTURAL
+  MUST ( ds-cfg-log-directory )
+  MAY ( ds-cfg-csv-quote-char $
+        ds-cfg-csv-delimiter-char $
+        ds-cfg-csv-eol-symbols $
+        ds-cfg-auto-flush $
+        ds-cfg-asynchronous $
+        ds-cfg-rotation-policy $
+        ds-cfg-retention-policy $
+        ds-cfg-tamper-evident $
+        ds-cfg-signature-time-interval $
+        ds-cfg-key-store-file $
+        ds-cfg-key-store-pin-file )
+  X-ORIGIN 'OpenDJ Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.30
+  NAME 'ds-cfg-external-access-log-publisher'
+  SUP ds-cfg-access-log-publisher
+  STRUCTURAL
+  MUST ( ds-cfg-config-file )
+  MAY ( ds-cfg-log-control-oids )
+  X-ORIGIN 'OpenDJ Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.31
+  NAME 'ds-cfg-external-http-access-log-publisher'
+  SUP ds-cfg-http-access-log-publisher
+  STRUCTURAL
+  MUST ( ds-cfg-config-file )
+  X-ORIGIN 'OpenDJ Directory Server' )
\ No newline at end of file
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/AdministrationConnector.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/AdministrationConnector.java
index 8be8b54..7056193 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/admin/AdministrationConnector.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/AdministrationConnector.java
@@ -116,6 +116,8 @@
   private static final SSLClientAuthPolicy ADMIN_SSL_CLIENT_AUTH_POLICY =
     SSLClientAuthPolicy.DISABLED;
 
+  private final ServerContext serverContext;
+
   /**
    * Initializes this administration connector provider based on the
    * information in the provided administration connector
@@ -142,7 +144,7 @@
     // Administration Connector uses the LDAP connection handler implementation
     adminConnectionHandler = new LDAPConnectionHandler(
         new SynchronousStrategy(), FRIENDLY_NAME);
-    adminConnectionHandler.initializeConnectionHandler(new LDAPConnectionCfgAdapter(config));
+    adminConnectionHandler.initializeConnectionHandler(serverContext, new LDAPConnectionCfgAdapter(config));
     adminConnectionHandler.setAdminConnectionHandler();
 
     // Register this as a change listener.
@@ -150,10 +152,15 @@
   }
 
 
-  /** Create an instance of the administration connector. */
-  public AdministrationConnector()
+  /**
+   * Creates an instance of the administration connector.
+   *
+   * @param serverContext
+   *            The server context.
+   **/
+  public AdministrationConnector(ServerContext serverContext)
   {
-    // Do nothing.
+    this.serverContext = serverContext;
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/ConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/api/ConnectionHandler.java
index ad3ce9f..6a6036b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/ConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/ConnectionHandler.java
@@ -27,13 +27,16 @@
 package org.opends.server.api;
 
 import static org.opends.messages.ProtocolMessages.*;
+
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.opends.server.admin.std.server.ConnectionHandlerCfg;
+import org.opends.server.core.ServerContext;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.monitors.ConnectionHandlerMonitor;
 import org.opends.server.types.DN;
@@ -191,6 +194,8 @@
    * Initializes this connection handler provider based on the
    * information in the provided connection handler configuration.
    *
+   * @param serverContext
+   *            The server context.
    * @param configuration
    *          The connection handler configuration that contains the
    *          information to use to initialize this connection
@@ -203,7 +208,7 @@
    *           If a problem occurs during initialization that is not
    *           related to the server configuration.
    */
-  public abstract void initializeConnectionHandler(T configuration)
+  public abstract void initializeConnectionHandler(ServerContext serverContext, T configuration)
       throws ConfigException, InitializationException;
 
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/controls/TransactionIdControl.java b/opendj-server-legacy/src/main/java/org/opends/server/controls/TransactionIdControl.java
new file mode 100644
index 0000000..3d454fd
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/controls/TransactionIdControl.java
@@ -0,0 +1,129 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.controls;
+
+import static org.opends.server.util.ServerConstants.OID_TRANSACTION_ID_CONTROL;
+
+import java.io.IOException;
+
+import org.forgerock.opendj.io.ASN1Writer;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.messages.ProtocolMessages;
+import org.opends.server.types.Control;
+import org.opends.server.types.DirectoryException;
+
+/**
+ * Control that provides a transaction ID.
+ * <p>
+ * The transaction ID is related to Common Audit : it is used for tracking the
+ * processing of a user-interaction as it passes through the Forgerock stack
+ * <p>
+ * The control's value is the UTF-8 encoding of the transaction ID.
+ */
+public class TransactionIdControl extends Control
+{
+  /** ControlDecoder implementation to decode this control from a ByteString. */
+  private static final class Decoder implements ControlDecoder<TransactionIdControl>
+  {
+    @Override
+    public TransactionIdControl decode(boolean isCritical, ByteString value) throws DirectoryException
+    {
+      if (value == null)
+      {
+        throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+            ProtocolMessages.ERR_TRANSACTION_ID_CONTROL_HAS_NO_VALUE.get());
+      }
+      return new TransactionIdControl(isCritical, value.toString());
+    }
+
+
+    @Override
+    public String getOID()
+    {
+      return OID_TRANSACTION_ID_CONTROL;
+    }
+
+  }
+
+  /** The Control Decoder that can be used to decode this control. */
+  public static final ControlDecoder<TransactionIdControl> DECODER = new Decoder();
+
+  /** The id value of this control. */
+  private final String transactionId;
+
+  /**
+   * Creates a new Transaction Id Control.
+   *
+   * @param  isCritical  Indicates whether this control should be considered
+   *                     critical to the operation processing.
+   * @param  transactionId The id to pass through this control.
+   */
+  public TransactionIdControl(boolean isCritical, String transactionId)
+  {
+    super(OID_TRANSACTION_ID_CONTROL, isCritical);
+    this.transactionId = transactionId;
+  }
+
+  /**
+   * Writes this control's value to an ASN.1 writer. The value (if any) must be
+   * written as an ASN1OctetString.
+   *
+   * @param writer
+   *          The ASN.1 output stream to write to.
+   * @throws IOException
+   *           If a problem occurs while writing to the stream.
+   */
+  @Override
+  public void writeValue(ASN1Writer writer) throws IOException
+  {
+    writer.writeOctetString(transactionId);
+  }
+
+  /**
+   * Retrieves the transaction id associated with this control.
+   *
+   * @return  The transaction id associated with this control.
+   */
+  public String getTransactionId()
+  {
+    return transactionId;
+  }
+
+  /**
+   * Appends a string representation of this control to the provided buffer.
+   *
+   * @param buffer
+   *          The buffer to which the information should be appended.
+   */
+  @Override
+  public void toString(StringBuilder buffer)
+  {
+    buffer.append("TransactionIdControl(id=");
+    buffer.append(transactionId);
+    buffer.append(")");
+  }
+}
\ No newline at end of file
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/ConnectionHandlerConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/ConnectionHandlerConfigManager.java
index 3664da4..e5eaef5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/ConnectionHandlerConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/ConnectionHandlerConfigManager.java
@@ -294,7 +294,7 @@
     AdministrationConnectorCfg administrationConnectorCfg =
       root.getAdministrationConnector();
 
-    AdministrationConnector ac = new AdministrationConnector();
+    AdministrationConnector ac = new AdministrationConnector(serverContext);
     ac.initializeAdministrationConnector(administrationConnectorCfg);
 
     // Put this connection handler in the hash so that we will be
@@ -354,7 +354,7 @@
           pd.loadClass(className, ConnectionHandler.class);
       ConnectionHandler<T> connectionHandler = theClass.newInstance();
 
-      connectionHandler.initializeConnectionHandler(config);
+      connectionHandler.initializeConnectionHandler(serverContext, config);
 
       return connectionHandler;
     } catch (Exception e) {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index 5d08ae7..ad3bfd2 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -138,6 +138,7 @@
 import org.opends.server.extensions.DiskSpaceMonitor;
 import org.opends.server.extensions.JMXAlertHandler;
 import org.opends.server.loggers.AccessLogger;
+import org.opends.server.loggers.CommonAudit;
 import org.opends.server.loggers.DebugLogPublisher;
 import org.opends.server.loggers.DebugLogger;
 import org.opends.server.loggers.ErrorLogPublisher;
@@ -726,6 +727,9 @@
   /** Entry point for server configuration. */
   private org.forgerock.opendj.config.server.ServerManagementContext serverManagementContext;
 
+  /** Entry point to common audit service, where all audit events must be published. */
+  private CommonAudit commonAudit;
+
   /** Class that prints the version of OpenDJ server to System.out. */
   public static final class DirectoryServerVersionHandler implements VersionHandler
   {
@@ -824,6 +828,12 @@
     {
       return directoryServer.diskSpaceMonitor;
     }
+
+    @Override
+    public CommonAudit getCommonAudit()
+    {
+      return directoryServer.commonAudit;
+    }
   }
 
   /**
@@ -1354,6 +1364,7 @@
       retentionPolicyConfigManager = new LogRetentionPolicyConfigManager(serverContext);
       retentionPolicyConfigManager.initializeLogRetentionPolicyConfig();
 
+      commonAudit = new CommonAudit();
       loggerConfigManager = new LoggerConfigManager(serverContext);
       loggerConfigManager.initializeLoggerConfig();
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/ServerContext.java b/opendj-server-legacy/src/main/java/org/opends/server/core/ServerContext.java
index ba1db9a..829e974 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/ServerContext.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/ServerContext.java
@@ -27,6 +27,7 @@
 
 import org.forgerock.opendj.config.server.ServerManagementContext;
 import org.opends.server.extensions.DiskSpaceMonitor;
+import org.opends.server.loggers.CommonAudit;
 import org.opends.server.schema.SchemaUpdater;
 import org.opends.server.types.DirectoryEnvironmentConfig;
 import org.opends.server.types.Schema;
@@ -107,4 +108,11 @@
    * @return the Disk Space Monioring service
    */
   DiskSpaceMonitor getDiskSpaceMonitor();
+
+  /**
+   * Returns the common audit manager.
+   *
+   * @return the common audit manager
+   */
+  CommonAudit getCommonAudit();
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/AbstractLogger.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/AbstractLogger.java
index 3c03ba8..d00339f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/AbstractLogger.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/AbstractLogger.java
@@ -26,6 +26,7 @@
  */
 package org.opends.server.loggers;
 
+import static org.opends.server.loggers.CommonAudit.*;
 import static org.opends.messages.ConfigMessages.*;
 import static org.opends.server.util.StaticUtils.*;
 
@@ -185,7 +186,7 @@
   private final Arg3<Object, Object, Object>
       invalidLoggerClassErrorMessage;
 
-  ServerContext serverContext;
+  private ServerContext serverContext;
 
   /**
    * The constructor for this class.
@@ -226,13 +227,20 @@
     {
       config.addChangeListener((ConfigurationChangeListener) this);
 
-      if(config.isEnabled())
+      if (config.isEnabled())
       {
-        addLogPublisher(getLogPublisher(config));
+        final P logPublisher = isCommonAuditConfig(config) ?
+            getLogPublisherForCommonAudit(config) : getLogPublisher(config);
+        addLogPublisher(logPublisher);
       }
     }
   }
 
+  ServerContext getServerContext()
+  {
+    return serverContext;
+  }
+
   /** {@inheritDoc} */
   @Override
   public boolean isConfigurationAddAcceptable(C config,
@@ -263,7 +271,9 @@
     {
       try
       {
-        addLogPublisher(getLogPublisher(config));
+        final P logPublisher = isCommonAuditConfig(config) ?
+            getLogPublisherForCommonAudit(config) : getLogPublisher(config);
+        addLogPublisher(logPublisher);
       }
       catch(ConfigException e)
       {
@@ -274,8 +284,7 @@
       catch (Exception e)
       {
         LocalizedLogger.getLoggerForThisClass().traceException(e);
-        ccr.addMessage(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
-            config.dn(), stackTraceToSingleLineString(e)));
+        ccr.addMessage(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(config.dn(), stackTraceToSingleLineString(e)));
         ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
       }
     }
@@ -301,9 +310,9 @@
     final ConfigChangeResult ccr = new ConfigChangeResult();
 
     P logPublisher = findLogPublisher(config.dn());
-    if(logPublisher == null)
+    if (logPublisher == null)
     {
-      if(config.isEnabled())
+      if (config.isEnabled())
       {
         // Needs to be added and enabled.
         return applyConfigurationAdd(config);
@@ -311,26 +320,38 @@
     }
     else
     {
-      if(config.isEnabled())
+      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()))
+        if (!className.equals(logPublisher.getClass().getName()))
         {
           ccr.setAdminActionRequired(true);
         }
+        try
+        {
+          if (isCommonAuditConfig(config))
+          {
+            serverContext.getCommonAudit().addOrUpdatePublisher(config);
+          } // else the publisher is currently active, so we don't need to do
+            // anything.
+        }
+        catch (Exception e)
+        {
+          LocalizedLogger.getLoggerForThisClass().traceException(e);
+          ccr.addMessage(ERR_CONFIG_LOGGER_CANNOT_UPDATE_LOGGER.get(config.dn(), stackTraceToSingleLineString(e)));
+          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+        }
       }
       else
       {
         // The publisher is being disabled so shut down and remove.
-        removeLogPublisher(logPublisher);
+        return applyConfigurationDelete(config);
       }
     }
-
     return ccr;
   }
 
@@ -342,7 +363,6 @@
     return findLogPublisher(config.dn()) != null;
   }
 
-  /** {@inheritDoc} */
   @Override
   public ConfigChangeResult applyConfigurationDelete(C config)
   {
@@ -352,6 +372,19 @@
     if(logPublisher != null)
     {
       removeLogPublisher(logPublisher);
+      try
+      {
+        if (isCommonAuditConfig(config))
+        {
+          serverContext.getCommonAudit().removePublisher(config);
+        }
+      }
+      catch (ConfigException e)
+      {
+        LocalizedLogger.getLoggerForThisClass().traceException(e);
+        ccr.addMessage(ERR_CONFIG_LOGGER_CANNOT_DELETE_LOGGER.get(config.dn(), stackTraceToSingleLineString(e)));
+        ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+      }
     }
     else
     {
@@ -391,4 +424,14 @@
     }
   }
 
+  private P getLogPublisherForCommonAudit(C config) throws InitializationException, ConfigException
+  {
+    CommonAudit commonAudit = serverContext.getCommonAudit();
+    commonAudit.addOrUpdatePublisher(config);
+    P logPublisher = getLogPublisher(config);
+    CommonAuditLogPublisher publisher = (CommonAuditLogPublisher) logPublisher;
+    publisher.setRequestHandler(commonAudit.getRequestHandler(config));
+    return logPublisher;
+  }
+
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/AccessLogger.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/AccessLogger.java
index 0ae3ead..fd2df90 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/AccessLogger.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/AccessLogger.java
@@ -521,6 +521,7 @@
   public final synchronized void removeAllLogPublishers()
   {
     loggerStorage.removeAllLogPublishers();
+    getServerContext().getCommonAudit().shutdown();
   }
 }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
new file mode 100644
index 0000000..aa413b1
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
@@ -0,0 +1,943 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS.
+ */
+package org.opends.server.loggers;
+
+import static org.opends.messages.LoggerMessages.*;
+import static java.util.Collections.newSetFromMap;
+import static org.forgerock.audit.AuditServiceBuilder.newAuditService;
+import static org.forgerock.audit.events.EventTopicsMetaDataBuilder.coreTopicSchemas;
+import static org.forgerock.audit.json.AuditJsonConfig.registerHandlerToService;
+import static org.opends.server.util.StaticUtils.getFileForPath;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+
+import org.forgerock.audit.AuditException;
+import org.forgerock.audit.AuditService;
+import org.forgerock.audit.AuditServiceBuilder;
+import org.forgerock.audit.AuditServiceConfiguration;
+import org.forgerock.audit.AuditServiceProxy;
+import org.forgerock.audit.DependencyProvider;
+import org.forgerock.audit.events.EventTopicsMetaData;
+import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRetention;
+import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRotation;
+import org.forgerock.audit.handlers.csv.CsvAuditEventHandler;
+import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration;
+import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration.CsvFormatting;
+import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration.CsvSecurity;
+import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration.EventBufferingConfiguration;
+import org.forgerock.audit.json.AuditJsonConfig;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.json.JsonValue;
+import org.forgerock.json.resource.RequestHandler;
+import org.forgerock.opendj.config.ConfigurationFramework;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.admin.Configuration;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.server.CsvFileAccessLogPublisherCfg;
+import org.opends.server.admin.std.server.CsvFileHTTPAccessLogPublisherCfg;
+import org.opends.server.admin.std.server.ExternalAccessLogPublisherCfg;
+import org.opends.server.admin.std.server.ExternalHTTPAccessLogPublisherCfg;
+import org.opends.server.admin.std.server.FileCountLogRetentionPolicyCfg;
+import org.opends.server.admin.std.server.FixedTimeLogRotationPolicyCfg;
+import org.opends.server.admin.std.server.FreeDiskSpaceLogRetentionPolicyCfg;
+import org.opends.server.admin.std.server.LogPublisherCfg;
+import org.opends.server.admin.std.server.LogRetentionPolicyCfg;
+import org.opends.server.admin.std.server.LogRotationPolicyCfg;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.admin.std.server.SizeLimitLogRetentionPolicyCfg;
+import org.opends.server.admin.std.server.SizeLimitLogRotationPolicyCfg;
+import org.opends.server.admin.std.server.TimeLimitLogRotationPolicyCfg;
+import org.opends.server.config.ConfigEntry;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.DN;
+import org.opends.server.util.StaticUtils;
+
+/**
+ * Entry point for the common audit facility.
+ * <p>
+ * This class manages the AuditService instances and Audit Event Handlers that correspond to the
+ * publishers defined in OpenDJ configuration.
+ * <p>
+ * In theory there should be only one instance of AuditService for all the event handlers but
+ * defining one service per handler allow to perform filtering at the DJ server level.
+ */
+public class CommonAudit
+{
+
+  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+  private static final String AUDIT_SERVICE_JSON_CONFIGURATION_FILE = "audit-config.json";
+
+  /** Dependency provider used to instantiate the handlers. */
+  private final DependencyProvider dependencyProvider;
+
+  /** Configuration framework is used to get an up-to-date class loader with any external library available. */
+  private final ConfigurationFramework configurationFramework;
+
+  /** Cache of audit services per configuration entry name. */
+  private final Map<String, AuditServiceProxy> auditServiceCache = new ConcurrentHashMap<>(10);
+
+  private final Set<PublisherConfig> httpAccessPublishers =
+      newSetFromMap(new ConcurrentHashMap<PublisherConfig, Boolean>(10));
+
+  /** Audit service shared by all HTTP access publishers. */
+  private final AuditServiceProxy httpAccessAuditService;
+
+
+  /**
+   * Creates the common audit.
+   *
+   * @throws ConfigException
+   *           If an error occurs.
+   */
+  public CommonAudit() throws ConfigException
+  {
+    configurationFramework = ConfigurationFramework.getInstance();
+    this.dependencyProvider = new CommonAuditDependencyProvider();
+    this.httpAccessAuditService = createAuditServiceWithoutHandlers();
+  }
+
+  private AuditServiceProxy createAuditServiceWithoutHandlers() throws ConfigException
+  {
+    try
+    {
+      return buildAuditService(new AuditServiceSetup()
+      {
+        @Override
+        public void addHandlers(AuditServiceBuilder builder)
+        {
+          // no handler to add
+        }
+      });
+    }
+    catch (IOException | ConfigException | AuditException e)
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_CREATE.get(e), e);
+    }
+  }
+
+  /**
+   * Returns the Common Audit request handler for the provided configuration.
+   *
+   * @param config
+   *            The log publisher configuration
+   * @return the request handler associated to the log publisher
+   * @throws ConfigException
+   *            If an error occurs
+   */
+  public RequestHandler getRequestHandler(LogPublisherCfg config) throws ConfigException
+  {
+    if (new PublisherConfig(config).isHttpAccessLog())
+    {
+      return httpAccessAuditService;
+    }
+    return auditServiceCache.get(getNameFromConfig(config));
+  }
+
+  /**
+   * Adds or updates the publisher corresponding to the provided configuration to common audit.
+   *
+   * @param newConfig
+   *          Configuration of the publisher
+   * @throws ConfigException
+   *           If an error occurs.
+   */
+  public void addOrUpdatePublisher(final LogPublisherCfg newConfig) throws ConfigException
+  {
+    if (newConfig.isEnabled())
+    {
+      logger.trace("Setting up common audit for configuration entry: " + newConfig.dn());
+      try
+      {
+        final PublisherConfig newPublisher = new PublisherConfig(newConfig);
+        if (newPublisher.isHttpAccessLog())
+        {
+          if (httpAccessPublishers.contains(newPublisher))
+          {
+            // remove the old version before adding the new one
+            httpAccessPublishers.remove(newPublisher);
+          }
+          httpAccessPublishers.add(newPublisher);
+          buildAuditService(httpAccessAuditServiceSetup());
+        }
+        else // all other logs
+        {
+          String name = newPublisher.getName();
+          final AuditServiceProxy existingService =
+              auditServiceCache.containsKey(name) ? auditServiceCache.get(name): null;
+          AuditServiceProxy auditService = buildAuditService(new AuditServiceSetup(existingService)
+          {
+            @Override
+            public void addHandlers(AuditServiceBuilder builder) throws ConfigException
+            {
+              registerHandlerName(newPublisher.getName());
+              addHandlerToBuilder(newPublisher, builder);
+            }
+          });
+          auditServiceCache.put(name, auditService);
+        }
+      }
+      catch (Exception e)
+      {
+        throw new ConfigException(ERR_COMMON_AUDIT_ADD_OR_UPDATE_LOG_PUBLISHER.get(newConfig.dn(), e), e);
+      }
+    }
+  }
+
+  /**
+   * Removes the publisher corresponding to the provided configuration from common audit.
+   *
+   * @param config
+   *          Configuration of publisher to remove
+   * @throws ConfigException
+   *            If an error occurs.
+   */
+  public void removePublisher(LogPublisherCfg config) throws ConfigException
+  {
+    final PublisherConfig publisher = new PublisherConfig(config);
+    logger.trace("Shutting down common audit for configuration entry:" + config.dn());
+    try
+    {
+      if (publisher.isHttpAccessLog())
+      {
+        httpAccessPublishers.remove(publisher);
+        buildAuditService(httpAccessAuditServiceSetup());
+      }
+      else // all other logs
+      {
+        AuditServiceProxy auditService = auditServiceCache.remove(publisher.getName());
+        if (auditService != null)
+        {
+          auditService.shutdown();
+        }
+      }
+    }
+    catch (Exception e)
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_REMOVE_LOG_PUBLISHER.get(config.dn(), e), e);
+    }
+  }
+
+  /** Shutdown common audit. */
+  public void shutdown()
+  {
+    httpAccessAuditService.shutdown();
+    for (AuditServiceProxy service : auditServiceCache.values())
+    {
+      service.shutdown();
+    }
+  }
+
+  private AuditServiceSetup httpAccessAuditServiceSetup()
+  {
+    return new AuditServiceSetup(httpAccessAuditService)
+    {
+      @Override
+      public void addHandlers(AuditServiceBuilder builder) throws ConfigException
+      {
+        for (PublisherConfig publisher : httpAccessPublishers)
+        {
+          registerHandlerName(publisher.getName());
+          addHandlerToBuilder(publisher, builder);
+        }
+      }
+    };
+  }
+
+  /**
+   * Strategy for the setup of AuditService.
+   * <p>
+   * Unless no handler must be added, this class should be extended and
+   * implementations should override the {@code addHandlers()} method.
+   */
+  static abstract class AuditServiceSetup
+  {
+    private final AuditServiceProxy existingAuditServiceProxy;
+    private final List<String> names = new ArrayList<>();
+
+    /** Creation with no existing audit service. */
+    AuditServiceSetup()
+    {
+      this.existingAuditServiceProxy = null;
+    }
+
+    /** Creation with an existing audit service. */
+    AuditServiceSetup(AuditServiceProxy existingAuditService)
+    {
+      this.existingAuditServiceProxy = existingAuditService;
+    }
+
+    abstract void addHandlers(AuditServiceBuilder builder) throws ConfigException;
+
+    void registerHandlerName(String name)
+    {
+      names.add(name);
+    }
+
+    List<String> getHandlerNames()
+    {
+      return names;
+    }
+
+    boolean mustCreateAuditServiceProxy()
+    {
+      return existingAuditServiceProxy == null;
+    }
+
+    AuditServiceProxy getExistingAuditServiceProxy()
+    {
+      return existingAuditServiceProxy;
+    }
+
+  }
+
+  private AuditServiceProxy buildAuditService(AuditServiceSetup setup)
+      throws IOException, AuditException, ConfigException
+  {
+    final JsonValue jsonConfig;
+    try (InputStream input = getClass().getResourceAsStream(AUDIT_SERVICE_JSON_CONFIGURATION_FILE))
+    {
+      jsonConfig = AuditJsonConfig.getJson(input);
+    }
+
+    EventTopicsMetaData eventTopicsMetaData = coreTopicSchemas()
+        .withCoreTopicSchemaExtensions(jsonConfig.get("extensions"))
+        .withAdditionalTopicSchemas(jsonConfig.get("additionalTopics"))
+        .build();
+    AuditServiceBuilder builder = newAuditService()
+        .withEventTopicsMetaData(eventTopicsMetaData)
+        .withDependencyProvider(dependencyProvider);
+
+    setup.addHandlers(builder);
+
+    AuditServiceConfiguration auditConfig = new AuditServiceConfiguration();
+    auditConfig.setAvailableAuditEventHandlers(setup.getHandlerNames());
+    builder.withConfiguration(auditConfig);
+    AuditService audit = builder.build();
+
+    final AuditServiceProxy proxy;
+    if (setup.mustCreateAuditServiceProxy())
+    {
+      proxy = new AuditServiceProxy(audit);
+      logger.trace("Starting up new common audit service");
+      proxy.startup();
+    }
+    else
+    {
+      proxy = setup.getExistingAuditServiceProxy();
+      proxy.setDelegate(audit);
+      logger.trace("Starting up existing updated common audit service");
+    }
+    return proxy;
+  }
+
+  private void addHandlerToBuilder(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
+  {
+    if (publisher.isCsv())
+    {
+      addCsvHandler(publisher, builder);
+    }
+    else if (publisher.isExternal())
+    {
+      addExternalHandler(publisher, builder);
+    }
+    else
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_HANDLER_TYPE.get(publisher.getDn()));
+    }
+  }
+
+  /** Add a handler defined externally in a JSON configuration file. */
+  private void addExternalHandler(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
+  {
+    ExternalConfigData config = publisher.getExternalConfig();
+    File configFile = getFileForPath(config.getConfigurationFile());
+    try (InputStream input = new BufferedInputStream(new FileInputStream(configFile)))
+    {
+      JsonValue jsonConfig = AuditJsonConfig.getJson(input);
+      registerHandlerToService(jsonConfig, builder, configurationFramework.getClassLoader());
+    }
+    catch (IOException e)
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_EXTERNAL_HANDLER_JSON_FILE.get(configFile, publisher.getDn(), e), e);
+    }
+    catch (Exception e)
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_EXTERNAL_HANDLER_CREATION.get(publisher.getDn(), e), e);
+    }
+  }
+
+  private void addCsvHandler(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
+  {
+    String name = publisher.getName();
+    try
+    {
+      CsvConfigData config = publisher.getCsvConfig();
+      CsvAuditEventHandlerConfiguration csvConfig = new CsvAuditEventHandlerConfiguration();
+      File logDirectory = getFileForPath(config.getLogDirectory());
+      csvConfig.setLogDirectory(logDirectory.getAbsolutePath());
+      csvConfig.setName(name);
+      csvConfig.setTopics(Collections.singleton(publisher.getCommonAuditTopic()));
+
+      addCsvHandlerFormattingConfig(config, csvConfig);
+      addCsvHandlerBufferingConfig(config, csvConfig);
+      addCsvHandlerSecureConfig(config, csvConfig);
+      addCsvHandlerRotationConfig(publisher, config, csvConfig);
+      addCsvHandlerRetentionConfig(publisher, config, csvConfig);
+
+      builder.withAuditEventHandler(CsvAuditEventHandler.class, csvConfig);
+    }
+    catch (Exception e)
+    {
+      throw new ConfigException(ERR_COMMON_AUDIT_CSV_HANDLER_CREATION.get(publisher.getDn(), e), e);
+    }
+  }
+
+  private void addCsvHandlerFormattingConfig(CsvConfigData config, CsvAuditEventHandlerConfiguration auditConfig)
+      throws ConfigException
+  {
+    CsvFormatting formatting = new CsvFormatting();
+    formatting.setQuoteChar(config.getQuoteChar());
+    formatting.setDelimiterChar(config.getDelimiterChar());
+    String endOfLineSymbols = config.getEndOfLineSymbols();
+    if (endOfLineSymbols != null && !endOfLineSymbols.isEmpty())
+    {
+      formatting.setEndOfLineSymbols(endOfLineSymbols);
+    }
+    auditConfig.setFormatting(formatting);
+  }
+
+  private void addCsvHandlerBufferingConfig(CsvConfigData config, CsvAuditEventHandlerConfiguration auditConfig)
+  {
+    EventBufferingConfiguration bufferingConfig = new EventBufferingConfiguration();
+    bufferingConfig.setEnabled(config.isAsynchronous());
+    bufferingConfig.setAutoFlush(config.isAutoFlush());
+    auditConfig.setBufferingConfiguration(bufferingConfig);
+  }
+
+  private void addCsvHandlerSecureConfig(CsvConfigData config, CsvAuditEventHandlerConfiguration auditConfig)
+  {
+    if (config.isTamperEvident())
+    {
+      CsvSecurity security = new CsvSecurity();
+      security.setSignatureInterval(config.getSignatureTimeInterval() + "ms");
+      security.setEnabled(true);
+      String keyStoreFile = config.getKeystoreFile();
+      security.setFilename(getFileForPath(keyStoreFile).getPath());
+      security.setPassword(getSecurePassword(config));
+      auditConfig.setSecurity(security);
+    }
+  }
+
+  private void addCsvHandlerRotationConfig(PublisherConfig publisher, CsvConfigData config,
+      CsvAuditEventHandlerConfiguration auditConfig) throws ConfigException
+  {
+    RootCfg root = ServerManagementContext.getInstance().getRootConfiguration();
+    SortedSet<String> rotationPolicies = config.getRotationPolicies();
+    if (rotationPolicies.isEmpty())
+    {
+      return;
+    }
+
+    FileRotation fileRotation = new FileRotation();
+    fileRotation.setRotationEnabled(true);
+    for (final String policy : rotationPolicies)
+    {
+      LogRotationPolicyCfg policyConfig = root.getLogRotationPolicy(policy);
+      if (policyConfig instanceof FixedTimeLogRotationPolicyCfg)
+      {
+        List<String> times = convertTimesOfDay(publisher, (FixedTimeLogRotationPolicyCfg) policyConfig);
+        fileRotation.setRotationTimes(times);
+      }
+      else if (policyConfig instanceof SizeLimitLogRotationPolicyCfg)
+      {
+        fileRotation.setMaxFileSize(((SizeLimitLogRotationPolicyCfg) policyConfig).getFileSizeLimit());
+      }
+      else if (policyConfig instanceof TimeLimitLogRotationPolicyCfg)
+      {
+        long rotationInterval = ((TimeLimitLogRotationPolicyCfg) policyConfig).getRotationInterval();
+        fileRotation.setRotationInterval(String.valueOf(rotationInterval) + " ms");
+      }
+      else
+      {
+        throw new ConfigException(
+            ERR_COMMON_AUDIT_UNSUPPORTED_LOG_ROTATION_POLICY.get(publisher.getDn(), policyConfig.dn()));
+      }
+    }
+    auditConfig.setFileRotation(fileRotation);
+  }
+
+  private void addCsvHandlerRetentionConfig(PublisherConfig publisher, CsvConfigData config,
+      CsvAuditEventHandlerConfiguration auditConfig) throws ConfigException
+  {
+    RootCfg root = ServerManagementContext.getInstance().getRootConfiguration();
+    SortedSet<String> retentionPolicies = config.getRetentionPolicies();
+    if (retentionPolicies.isEmpty())
+    {
+      return;
+    }
+
+    FileRetention fileRetention = new FileRetention();
+    for (final String policy : retentionPolicies)
+    {
+      LogRetentionPolicyCfg policyConfig = root.getLogRetentionPolicy(policy);
+      if (policyConfig instanceof FileCountLogRetentionPolicyCfg)
+      {
+        fileRetention.setMaxNumberOfHistoryFiles(((FileCountLogRetentionPolicyCfg) policyConfig).getNumberOfFiles());
+      }
+      else if (policyConfig instanceof FreeDiskSpaceLogRetentionPolicyCfg)
+      {
+        // TODO: remove the cast to int when fixed
+        fileRetention.setMinFreeSpaceRequired(
+            (int)((FreeDiskSpaceLogRetentionPolicyCfg) policyConfig).getFreeDiskSpace());
+      }
+      else if (policyConfig instanceof SizeLimitLogRetentionPolicyCfg)
+      {
+        fileRetention.setMaxDiskSpaceToUse(((SizeLimitLogRetentionPolicyCfg) policyConfig).getDiskSpaceUsed());
+      }
+      else
+      {
+        throw new ConfigException(
+            ERR_COMMON_AUDIT_UNSUPPORTED_LOG_RETENTION_POLICY.get(publisher.getDn(), policyConfig.dn()));
+      }
+    }
+    auditConfig.setFileRetention(fileRetention);
+  }
+
+  /**
+   * Convert the set of provided times of day using 24-hour format "HHmm" to a list of
+   * times of day using duration in minutes, e.g "20 minutes".
+   * <p>
+   * Example: "0230" => "150 minutes"
+   */
+  private List<String> convertTimesOfDay(PublisherConfig publisher, FixedTimeLogRotationPolicyCfg policyConfig)
+      throws ConfigException
+  {
+    SortedSet<String> timesOfDay = policyConfig.getTimeOfDay();
+    List<String> times = new ArrayList<>();
+    for (String timeOfDay : timesOfDay)
+    {
+      try
+      {
+        int time = Integer.valueOf(timeOfDay.substring(0, 2)) * 60 + Integer.valueOf(timeOfDay.substring(2, 4));
+        times.add(String.valueOf(time) + " minutes");
+      }
+      catch (NumberFormatException | IndexOutOfBoundsException e)
+      {
+        throw new ConfigException(ERR_COMMON_AUDIT_INVALID_TIME_OF_DAY.get(publisher.getDn(), timeOfDay,
+            StaticUtils.stackTraceToSingleLineString(e)));
+      }
+    }
+    return times;
+  }
+
+  // TODO : this method will be deleted, because a keystore handler will be used instead
+  private String getSecurePassword(CsvConfigData config)
+  {
+    String fileName = config.getKeystorePinFile();
+    File   pinFile  = getFileForPath(fileName);
+
+    if (!pinFile.exists())
+    {
+      // should log error "no pin file"
+    }
+    else
+    {
+      String pinStr = null;
+      BufferedReader br = null;
+      try {
+        br = new BufferedReader(new FileReader(pinFile));
+        pinStr = br.readLine();
+      }
+      catch (IOException ioe)
+      {
+        // should log error "unable to read pin file"
+      }
+      finally
+      {
+        StaticUtils.close(br);
+      }
+
+      if (pinStr == null)
+      {
+        // should log error pin file empty
+      }
+      else
+      {
+        return pinStr;
+      }
+    }
+    return "";
+  }
+
+  private String getNameFromConfig(Configuration config)
+  {
+    return config.dn().getRDN(0).getAttributeValue(0).toString();
+  }
+
+  /**
+   * Indicates if the provided log publisher configuration corresponds to a common audit publisher.
+   *
+   * @param config
+   *            The log publisher configuration.
+   * @return {@code true} if publisher is for common audit
+   * @throws ConfigException
+   *            If an error occurs
+   */
+  public static boolean isCommonAuditConfig(LogPublisherCfg config) throws ConfigException
+  {
+    return new PublisherConfig(config).isCommonAudit();
+  }
+
+  /**
+   * Indicates if HTTP access logging is enabled for common audit.
+   *
+   * @return {@code true} if there is at least one HTTP access logger enabled for common audit.
+   */
+  public boolean isHttpAccessLogEnabled()
+  {
+    return !httpAccessPublishers.isEmpty();
+  }
+
+  /**
+   * Returns the audit service that manages HTTP Access logging.
+   *
+   * @return the request handler that accepts audit events
+   */
+  public RequestHandler getAuditServiceForHttpAccessLog()
+  {
+    return httpAccessAuditService;
+  }
+
+  /**
+   * This class hides all ugly code needed to determine which type of publisher and audit event handler is needed.
+   * <p>
+   * In particular, it allows to retrieve a common configuration that can be used for log publishers that
+   * publish to the same kind of handler.
+   * For example: for CSV handler, DJ configurations for the log publishers contain the same methods but
+   * do not have a common interface (CsvFileAccessLogPublisherCfg vs CsvFileHTTPAccessLogPublisherCfg).
+   */
+  private static class PublisherConfig
+  {
+    private final LogPublisherCfg config;
+    private final boolean isCommonAudit;
+    private LogType logType;
+    private AuditType auditType;
+
+    PublisherConfig(LogPublisherCfg config) throws ConfigException
+    {
+      this.config = config;
+      ConfigEntry configEntry = DirectoryServer.getConfigEntry(config.dn());
+      if (configEntry.hasObjectClass("ds-cfg-csv-file-access-log-publisher"))
+      {
+        auditType = AuditType.CSV;
+        logType = LogType.ACCESS;
+      }
+      else if (configEntry.hasObjectClass("ds-cfg-csv-file-http-access-log-publisher"))
+      {
+        auditType = AuditType.CSV;
+        logType = LogType.HTTP_ACCESS;
+      }
+      else if (configEntry.hasObjectClass("ds-cfg-external-access-log-publisher"))
+      {
+        auditType = AuditType.EXTERNAL;
+        logType = LogType.ACCESS;
+      }
+      else if (configEntry.hasObjectClass("ds-cfg-external-http-access-log-publisher"))
+      {
+        auditType = AuditType.EXTERNAL;
+        logType = LogType.HTTP_ACCESS;
+      }
+      isCommonAudit = auditType != null;
+    }
+
+    DN getDn()
+    {
+      return config.dn();
+    }
+
+    String getName()
+    {
+      return config.dn().getRDN(0).getAttributeValue(0).toString();
+    }
+
+    String getCommonAuditTopic() throws ConfigException
+    {
+      if (isAccessLog())
+      {
+        return "ldap-access";
+      }
+      else if (isHttpAccessLog())
+      {
+        return "http-access";
+      }
+      throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
+    }
+
+    boolean isExternal()
+    {
+      return AuditType.EXTERNAL == auditType;
+    }
+
+    boolean isCsv()
+    {
+      return AuditType.CSV == auditType;
+    }
+
+    boolean isAccessLog()
+    {
+      return LogType.ACCESS == logType;
+    }
+
+    boolean isHttpAccessLog()
+    {
+      return LogType.HTTP_ACCESS == logType;
+    }
+
+    boolean isCommonAudit()
+    {
+      return isCommonAudit;
+    }
+
+    CsvConfigData getCsvConfig() throws ConfigException
+    {
+      if (isAccessLog())
+      {
+        CsvFileAccessLogPublisherCfg conf = (CsvFileAccessLogPublisherCfg) config;
+        return new CsvConfigData(conf.getLogDirectory(), conf.getCsvQuoteChar(), conf.getCsvDelimiterChar(), conf
+            .getCsvEolSymbols(), conf.isAsynchronous(), conf.isAutoFlush(), conf.isTamperEvident(), conf
+            .getSignatureTimeInterval(), conf.getKeyStoreFile(), conf.getKeyStorePinFile(), conf.getRotationPolicy(),
+            conf.getRetentionPolicy());
+      }
+      if (isHttpAccessLog())
+      {
+        CsvFileHTTPAccessLogPublisherCfg conf = (CsvFileHTTPAccessLogPublisherCfg) config;
+        return new CsvConfigData(conf.getLogDirectory(), conf.getCsvQuoteChar(), conf.getCsvDelimiterChar(), conf
+            .getCsvEolSymbols(), conf.isAsynchronous(), conf.isAutoFlush(), conf.isTamperEvident(), conf
+            .getSignatureTimeInterval(), conf.getKeyStoreFile(), conf.getKeyStorePinFile(), conf.getRotationPolicy(),
+            conf.getRetentionPolicy());
+      }
+      throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
+    }
+
+    ExternalConfigData getExternalConfig() throws ConfigException
+    {
+      if (isAccessLog())
+      {
+        ExternalAccessLogPublisherCfg conf = (ExternalAccessLogPublisherCfg) config;
+        return new ExternalConfigData(conf.getConfigFile());
+      }
+      if (isHttpAccessLog())
+      {
+        ExternalHTTPAccessLogPublisherCfg conf = (ExternalHTTPAccessLogPublisherCfg) config;
+        return new ExternalConfigData(conf.getConfigFile());
+      }
+      throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (this == obj)
+      {
+        return true;
+      }
+      if (!(obj instanceof PublisherConfig))
+      {
+        return false;
+      }
+      PublisherConfig other = (PublisherConfig) obj;
+      return config.dn().equals(other.config.dn());
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return config.dn().hashCode();
+    }
+
+  }
+
+  /** Types of audit handlers managed. */
+  private enum AuditType
+  {
+    CSV, EXTERNAL
+  }
+
+  /** Types of log managed. */
+  private enum LogType
+  {
+    ACCESS, HTTP_ACCESS
+  }
+
+  /**
+   * Contains the parameters for a CSV handler.
+   * <p>
+   * OpenDJ log publishers that logs to a CSV handler have the same parameters but do not share
+   * a common ancestor with all the parameters (e.g Access Log, HTTP Access Log, ...), hence this class
+   * is necessary to avoid duplicating code that setup the configuration of the CSV handler.
+   */
+  private static class CsvConfigData
+  {
+    private final String logDirectory;
+    private final String eolSymbols;
+    private final String delimiterChar;
+    private final String quoteChar;
+    private final boolean asynchronous;
+    private final boolean autoFlush;
+    private final boolean tamperEvident;
+    private final long signatureTimeInterval;
+    private final String keystoreFile;
+    private final String keystorePinFile;
+    private final SortedSet<String> rotationPolicies;
+    private final SortedSet<String> retentionPolicies;
+
+    CsvConfigData(String logDirectory, String quoteChar, String delimiterChar, String eolSymbols, boolean asynchronous,
+        boolean autoFlush, boolean tamperEvident, long signatureTimeInterval, String keystoreFile,
+        String keystorePinFile, SortedSet<String> rotationPolicies, SortedSet<String> retentionPolicies)
+    {
+      this.logDirectory = logDirectory;
+      this.quoteChar = quoteChar;
+      this.delimiterChar = delimiterChar;
+      this.eolSymbols = eolSymbols;
+      this.asynchronous = asynchronous;
+      this.autoFlush = autoFlush;
+      this.tamperEvident = tamperEvident;
+      this.signatureTimeInterval = signatureTimeInterval;
+      this.keystoreFile = keystoreFile;
+      this.keystorePinFile = keystorePinFile;
+      this.rotationPolicies = rotationPolicies;
+      this.retentionPolicies = retentionPolicies;
+    }
+
+    String getEndOfLineSymbols()
+    {
+      return eolSymbols;
+    }
+
+    char getDelimiterChar() throws ConfigException
+    {
+      String filtered = delimiterChar.replaceAll(Pattern.quote("\\"), "");
+      if (filtered.length() != 1)
+      {
+        throw new ConfigException(ERR_COMMON_AUDIT_CSV_HANDLER_DELIMITER_CHAR.get("", filtered));
+      }
+      return filtered.charAt(0);
+    }
+
+    public char getQuoteChar() throws ConfigException
+    {
+      String filtered = quoteChar.replaceAll(Pattern.quote("\\"), "");
+      if (filtered.length() != 1)
+      {
+        throw new ConfigException(ERR_COMMON_AUDIT_CSV_HANDLER_QUOTE_CHAR.get("", filtered));
+      }
+      return filtered.charAt(0);
+    }
+
+    String getLogDirectory()
+    {
+      return logDirectory;
+    }
+
+    boolean isAsynchronous()
+    {
+      return asynchronous;
+    }
+
+    boolean isAutoFlush()
+    {
+      return autoFlush;
+    }
+
+    boolean isTamperEvident()
+    {
+      return tamperEvident;
+    }
+
+    long getSignatureTimeInterval()
+    {
+      return signatureTimeInterval;
+    }
+
+    String getKeystoreFile()
+    {
+      return keystoreFile;
+    }
+
+    String getKeystorePinFile()
+    {
+      return keystorePinFile;
+    }
+
+    SortedSet<String> getRotationPolicies()
+    {
+      return rotationPolicies;
+    }
+
+    SortedSet<String> getRetentionPolicies()
+    {
+      return retentionPolicies;
+    }
+  }
+
+  /**
+   * Contains the parameters for an external handler.
+   * <p>
+   * OpenDJ log publishers that logs to an external handler have the same parameters but do not share
+   * a common ancestor with all the parameters (e.g Access Log, HTTP Access Log, ...), hence this class
+   * is necessary to avoid duplicating code that setup the configuration of an external handler.
+   */
+  private static class ExternalConfigData
+  {
+    private final String configurationFile;
+
+    ExternalConfigData(String configurationFile)
+    {
+      this.configurationFile = configurationFile;
+    }
+
+    String getConfigurationFile()
+    {
+      return configurationFile;
+    }
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java
new file mode 100644
index 0000000..ffa63f6
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java
@@ -0,0 +1,554 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import static org.opends.messages.LoggerMessages.*;
+import static org.forgerock.json.JsonValue.json;
+import static org.forgerock.json.resource.Requests.newCreateRequest;
+import static org.forgerock.json.resource.ResourcePath.resourcePath;
+import static org.opends.server.loggers.OpenDJAccessAuditEventBuilder.openDJAccessEvent;
+import static org.opends.server.types.AuthenticationType.SASL;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.forgerock.audit.events.AccessAuditEventBuilder.ResponseStatus;
+import org.forgerock.audit.events.AuditEvent;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.json.resource.CreateRequest;
+import org.forgerock.json.resource.RequestHandler;
+import org.forgerock.json.resource.ResourceException;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.services.context.RootContext;
+import org.forgerock.util.Pair;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.RuntimeExceptionHandler;
+import org.opends.server.admin.std.server.AccessLogPublisherCfg;
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.ExtendedOperationHandler;
+import org.opends.server.controls.TransactionIdControl;
+import org.opends.server.core.AbandonOperation;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.BindOperation;
+import org.opends.server.core.CompareOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ExtendedOperation;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.core.ServerContext;
+import org.opends.server.core.UnbindOperation;
+import org.opends.server.types.AuthenticationInfo;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.Operation;
+import org.opends.server.util.ServerConstants;
+import org.opends.server.util.StaticUtils;
+
+/**
+ * Publishes access events to Common Audit.
+ *
+ * @param <T> the type of configuration
+ */
+abstract class CommonAuditAccessLogPublisher<T extends AccessLogPublisherCfg>
+  extends AbstractTextAccessLogPublisher<T>
+  implements CommonAuditLogPublisher
+{
+
+  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+  /** Transaction id used when the incoming request does not contain a transaction id. */
+  private static final String DEFAULT_TRANSACTION_ID = "0";
+
+  /** Audit service handler. */
+  private RequestHandler requestHandler;
+
+  /** Current configuration for this publisher. */
+  private T config;
+
+  @Override
+  public void setRequestHandler(RequestHandler handler)
+  {
+    this.requestHandler = handler;
+  }
+
+  abstract boolean shouldLogControlOids();
+
+  T getConfig()
+  {
+    return config;
+  }
+
+  void setConfig(T config)
+  {
+    this.config = config;
+  }
+
+  @Override
+  public void initializeLogPublisher(final T cfg, ServerContext serverContext)
+      throws ConfigException, InitializationException
+  {
+    initializeFilters(cfg);
+    config = cfg;
+  }
+
+  @Override
+  public boolean isConfigurationAcceptable(final T configuration, final List<LocalizableMessage> unacceptableReasons)
+  {
+    return isFilterConfigurationAcceptable(configuration, unacceptableReasons);
+  }
+
+  @Override
+  public void logAbandonResult(final AbandonOperation abandonOperation)
+  {
+    if (!isResponseLoggable(abandonOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(abandonOperation, "ABANDON");
+    appendAbandonRequest(abandonOperation, builder);
+    appendResultCodeAndMessage(abandonOperation, builder);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logAddResponse(final AddOperation addOperation)
+  {
+    if (!isResponseLoggable(addOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(addOperation, "ADD");
+    appendAddRequest(addOperation, builder);
+    appendResultCodeAndMessage(addOperation, builder);
+    DN proxiedAuthorizationDN = addOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logBindResponse(final BindOperation bindOperation)
+  {
+    if (!isResponseLoggable(bindOperation))
+    {
+      return;
+    }
+
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(bindOperation, "BIND");
+    appendBindRequest(bindOperation, builder);
+    appendResultCodeAndMessage(bindOperation, builder);
+
+    final LocalizableMessage failureMessage = bindOperation.getAuthFailureReason();
+    if (failureMessage != null)
+    {
+      // this code path is mutually exclusive with the if result code is success
+      // down below
+      builder.ldapFailureMessage(failureMessage.toString());
+      if (bindOperation.getSASLMechanism() != null && bindOperation.getSASLAuthUserEntry() != null)
+      { // SASL bind and we have successfully found a user entry for auth
+        builder.userId(bindOperation.getSASLAuthUserEntry().getName().toString());
+      }
+      else
+      { // SASL bind failed to find user entry for auth or simple bind
+        builder.userId(bindOperation.getRawBindDN().toString());
+      }
+    }
+
+    if (bindOperation.getResultCode() == ResultCode.SUCCESS)
+    {
+      // this code path is mutually exclusive with the if failure message exist
+      // just above
+      final AuthenticationInfo authInfo = bindOperation.getAuthenticationInfo();
+      if (authInfo != null)
+      {
+        final DN authDN = authInfo.getAuthenticationDN();
+        if (authDN != null)
+        {
+          builder.userId(authDN.toString());
+
+          final DN authzDN = authInfo.getAuthorizationDN();
+          if (!authDN.equals(authzDN))
+          {
+            builder.runAs(authzDN.toString());
+          }
+        }
+        else
+        {
+          builder.userId("");
+        }
+      }
+    }
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logCompareResponse(final CompareOperation compareOperation)
+  {
+    if (!isResponseLoggable(compareOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(compareOperation, "COMPARE");
+    appendCompareRequest(compareOperation, builder);
+    appendResultCodeAndMessage(compareOperation, builder);
+    DN proxiedAuthorizationDN = compareOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  private void appendProxiedAuthorizationDNIfNeeded(OpenDJAccessAuditEventBuilder<?> builder, DN proxiedAuthorizationDN)
+  {
+    if (proxiedAuthorizationDN != null)
+    {
+      builder.runAs(proxiedAuthorizationDN.toString());
+    }
+  }
+
+  @Override
+  public void logConnect(final ClientConnection clientConnection)
+  {
+    if (!isConnectLoggable(clientConnection))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = openDJAccessEvent()
+        .eventName("DJ-" + clientConnection.getProtocol() + "-" + "CONNECT")
+        .client(clientConnection.getClientAddress(), clientConnection.getClientPort())
+        .server(clientConnection.getServerAddress(), clientConnection.getServerPort())
+        .request(clientConnection.getProtocol(), "CONNECT")
+        .transactionId(DEFAULT_TRANSACTION_ID)
+        .response(ResponseStatus.SUCCESSFUL, String.valueOf(ResultCode.SUCCESS.intValue()), 0, TimeUnit.MILLISECONDS)
+        .ldapConnectionId(clientConnection.getConnectionID());
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logDeleteResponse(final DeleteOperation deleteOperation)
+  {
+    if (!isResponseLoggable(deleteOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(deleteOperation, "DELETE");
+    appendDeleteRequest(deleteOperation, builder);
+    appendResultCodeAndMessage(deleteOperation, builder);
+    DN proxiedAuthorizationDN = deleteOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logDisconnect(final ClientConnection clientConnection, final DisconnectReason disconnectReason,
+      final LocalizableMessage message)
+  {
+    if (!isDisconnectLoggable(clientConnection))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = openDJAccessEvent()
+        .eventName("DJ-" + clientConnection.getProtocol() + "-" + "DISCONNECT")
+        .client(clientConnection.getClientAddress(), clientConnection.getClientPort())
+        .server(clientConnection.getServerAddress(), clientConnection.getServerPort())
+        .request(clientConnection.getProtocol(),"DISCONNECT")
+        .transactionId(DEFAULT_TRANSACTION_ID)
+        .response(ResponseStatus.SUCCESSFUL, String.valueOf(ResultCode.SUCCESS.intValue()), 0, TimeUnit.MILLISECONDS)
+        .ldapConnectionId(clientConnection.getConnectionID())
+        .ldapReason(disconnectReason.toString())
+        .ldapMessage(message.toString());
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logExtendedResponse(final ExtendedOperation extendedOperation)
+  {
+    if (!isResponseLoggable(extendedOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(extendedOperation, "EXTENDED");
+    appendExtendedRequest(extendedOperation, builder);
+    appendResultCodeAndMessage(extendedOperation, builder);
+    final String oid = extendedOperation.getResponseOID();
+    if (oid != null)
+    {
+      final ExtendedOperationHandler<?> extOpHandler = DirectoryServer.getExtendedOperationHandler(oid);
+      if (extOpHandler != null)
+      {
+        String name = extOpHandler.getExtendedOperationName();
+        builder.ldapName(name);
+      }
+      builder.ldapOid(oid);
+    }
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logModifyDNResponse(final ModifyDNOperation modifyDNOperation)
+  {
+    if (!isResponseLoggable(modifyDNOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(modifyDNOperation, "MODIFYDN");
+    appendModifyDNRequest(modifyDNOperation, builder);
+    appendResultCodeAndMessage(modifyDNOperation, builder);
+    DN proxiedAuthorizationDN = modifyDNOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logModifyResponse(final ModifyOperation modifyOperation)
+  {
+    if (!isResponseLoggable(modifyOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(modifyOperation, "MODIFY");
+    appendModifyRequest(modifyOperation, builder);
+    appendResultCodeAndMessage(modifyOperation, builder);
+    DN proxiedAuthorizationDN = modifyOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logSearchResultDone(final SearchOperation searchOperation)
+  {
+    if (!isResponseLoggable(searchOperation))
+    {
+      return;
+    }
+    OpenDJAccessAuditEventBuilder<?> builder = getEventBuilder(searchOperation, "SEARCH");
+    builder
+        .ldapSearch(searchOperation)
+        .ldapNEntries(searchOperation.getEntriesSent());
+        appendResultCodeAndMessage(searchOperation, builder);
+    DN proxiedAuthorizationDN = searchOperation.getProxiedAuthorizationDN();
+    appendProxiedAuthorizationDNIfNeeded(builder, proxiedAuthorizationDN);
+
+    sendEvent(builder.toEvent());
+  }
+
+  @Override
+  public void logUnbind(final UnbindOperation unbindOperation)
+  {
+    if (!isRequestLoggable(unbindOperation))
+    {
+      return;
+    }
+    sendEvent(getEventBuilder(unbindOperation, "UNBIND").toEvent());
+  }
+
+  @Override
+  protected void close0()
+  {
+    // nothing to do because closing is managed in the CommonAudit class
+  }
+
+  private void appendAbandonRequest(final AbandonOperation abandonOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapIdToAbandon(abandonOperation.getIDToAbandon());
+  }
+
+  private void appendAddRequest(final AddOperation addOperation, OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapDn(addOperation.getRawEntryDN().toString());
+  }
+
+  private void appendBindRequest(final BindOperation bindOperation, final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapProtocolVersion(bindOperation.getProtocolVersion());
+    final String authType = bindOperation.getAuthenticationType() != SASL ?
+        bindOperation.getAuthenticationType().toString() : "SASL mechanism=" + bindOperation.getSASLMechanism();
+    builder.ldapAuthType(authType);
+
+    builder.ldapDn(bindOperation.getRawBindDN().toString());
+
+  }
+
+  private void appendCompareRequest(final CompareOperation compareOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapDn(compareOperation.getRawEntryDN().toString());
+    builder.ldapAttr(compareOperation.getAttributeType().getNameOrOID());
+  }
+
+  private void appendDeleteRequest(final DeleteOperation deleteOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapDn(deleteOperation.getRawEntryDN().toString());
+  }
+
+  private void appendExtendedRequest(final ExtendedOperation extendedOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    final String oid = extendedOperation.getRequestOID();
+    final ExtendedOperationHandler<?> extOpHandler = DirectoryServer.getExtendedOperationHandler(oid);
+    if (extOpHandler != null)
+    {
+      final String name = extOpHandler.getExtendedOperationName();
+      builder.ldapName(name);
+    }
+    builder.ldapOid(oid);
+  }
+
+  private void appendModifyDNRequest(final ModifyDNOperation modifyDNOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapDn(modifyDNOperation.getRawEntryDN().toString());
+    builder.ldapModifyDN(modifyDNOperation);
+  }
+
+  private void appendModifyRequest(final ModifyOperation modifyOperation,
+      final OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    builder.ldapDn(modifyOperation.getRawEntryDN().toString());
+  }
+
+  private OpenDJAccessAuditEventBuilder<?> appendResultCodeAndMessage(
+      Operation operation, OpenDJAccessAuditEventBuilder<?> builder)
+  {
+    final LocalizableMessageBuilder message = operation.getErrorMessage();
+    int resultCode = operation.getResultCode().intValue();
+    ResponseStatus status = resultCode == 0 ? ResponseStatus.SUCCESSFUL : ResponseStatus.FAILED;
+    Pair<Long, TimeUnit> executionTime = getExecutionTime(operation);
+    if (message != null && message.length() > 0)
+    {
+      builder.responseWithDetail(status, String.valueOf(resultCode), executionTime.getFirst(),
+          executionTime.getSecond(), json(message.toString()));
+    }
+    else
+    {
+      builder.response(status, String.valueOf(resultCode), executionTime.getFirst(), executionTime.getSecond());
+    }
+    builder.ldapMaskedResultAndMessage(operation);
+    return builder;
+  }
+
+  /** Returns an event builder with all common fields filled. */
+  private OpenDJAccessAuditEventBuilder<?> getEventBuilder(final Operation operation, final String opType)
+  {
+    ClientConnection clientConn = operation.getClientConnection();
+
+    OpenDJAccessAuditEventBuilder<?> builder = openDJAccessEvent()
+      .eventName("DJ-" + clientConn.getProtocol() + "-" + opType)
+      .client(clientConn.getClientAddress(), clientConn.getClientPort())
+      .server(clientConn.getServerAddress(), clientConn.getServerPort())
+      .request(clientConn.getProtocol(), opType)
+      .ldapAdditionalItems(operation)
+      .ldapSync(operation)
+      .ldapIds(operation)
+      .transactionId(getTransactionId(operation));
+
+    if (shouldLogControlOids())
+    {
+      builder.ldapControls(operation);
+    }
+    return builder;
+  }
+
+  private String getTransactionId(Operation operation)
+  {
+    String transactionId = getTransactionIdFromControl(operation);
+    if (transactionId == null)
+    {
+      // use a default value because transaction id has no usage in this case
+      transactionId = DEFAULT_TRANSACTION_ID;
+    }
+    return transactionId;
+  }
+
+  private String getTransactionIdFromControl(Operation operation)
+  {
+    for (Control control : operation.getRequestControls())
+    {
+      if (control.getOID().equals(ServerConstants.OID_TRANSACTION_ID_CONTROL))
+      {
+        try
+        {
+          return operation.getRequestControl(TransactionIdControl.DECODER).getTransactionId();
+        }
+        catch (DirectoryException e)
+        {
+          logger.error(ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID.get(StaticUtils.stackTraceToSingleLineString(e)));
+        }
+      }
+    }
+    return null;
+  }
+
+  private Pair<Long,TimeUnit> getExecutionTime(final Operation operation)
+  {
+    Long etime = operation.getProcessingNanoTime();
+    // if not configured for nanos, use millis
+    return etime <= -1 ?
+        Pair.of(operation.getProcessingTime(), TimeUnit.MILLISECONDS) :
+        Pair.of(etime, TimeUnit.NANOSECONDS);
+  }
+
+  /** Sends an JSON-encoded event to the audit service. */
+  private void sendEvent(AuditEvent event)
+  {
+    CreateRequest request = newCreateRequest(resourcePath("/ldap-access"), event.getValue());
+    requestHandler
+      .handleCreate(new RootContext(), request)
+      .thenOnException(new ExceptionHandler<ResourceException>()
+        {
+          @Override
+          public void handleException(ResourceException e)
+          {
+            logger.error(ERR_COMMON_AUDIT_UNABLE_TO_PROCESS_LOG_EVENT.get(StaticUtils.stackTraceToSingleLineString(e)));
+          }
+        })
+      .thenOnRuntimeException(new RuntimeExceptionHandler()
+        {
+          @Override
+          public void handleRuntimeException(RuntimeException e)
+          {
+            logger.error(ERR_COMMON_AUDIT_UNABLE_TO_PROCESS_LOG_EVENT.get(StaticUtils.stackTraceToSingleLineString(e)));
+          }
+        });
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditDependencyProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditDependencyProvider.java
new file mode 100644
index 0000000..345bb7a
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditDependencyProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2013-2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.forgerock.audit.DependencyProvider;
+import org.forgerock.audit.providers.LocalHostNameProvider;
+import org.forgerock.audit.providers.ProductInfoProvider;
+import org.opends.server.util.DynamicConstants;
+
+/**
+ * Simple implementation of dependency provider for common audit.
+ */
+class CommonAuditDependencyProvider implements DependencyProvider
+{
+
+  @Override
+  public <T> T getDependency(Class<T> clazz) throws ClassNotFoundException
+  {
+    if (clazz.isAssignableFrom(LocalHostNameProvider.class))
+    {
+      return (T) new DJLocalHostNameProvider();
+    }
+    else if (clazz.isAssignableFrom(ProductInfoProvider.class))
+    {
+      return (T) new DJProductInfoProvider();
+    }
+    throw new ClassNotFoundException(String.format("Class %s could not be found", clazz));
+  }
+
+  /** DJ implementation for LocalHostNameProvider. */
+  private static class DJLocalHostNameProvider implements LocalHostNameProvider
+  {
+    @Override
+    public String getLocalHostName()
+    {
+      try
+      {
+        return InetAddress.getLocalHost().getHostName();
+      }
+      catch (UnknownHostException uhe)
+      {
+        return null;
+      }
+    }
+  }
+
+  /** DJ implementation for ProductInfoProvider. */
+  private static class DJProductInfoProvider implements ProductInfoProvider
+  {
+
+    @Override
+    public String getProductName()
+    {
+      return DynamicConstants.PRODUCT_NAME;
+    }
+
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditHTTPAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditHTTPAccessLogPublisher.java
new file mode 100644
index 0000000..8e63998
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditHTTPAccessLogPublisher.java
@@ -0,0 +1,109 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import java.util.List;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.json.resource.RequestHandler;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.HTTPAccessLogPublisherCfg;
+import org.opends.server.core.ServerContext;
+import org.opends.server.types.DN;
+
+/**
+ * Publishes HTTP access events to the common audit service.
+ * <p>
+ * This class actually does nothing because HTTP access logging is managed by a CHF filter.
+ * (See LdapHttpApplication)
+ *
+ * @param <T> the type of configuration
+ */
+class CommonAuditHTTPAccessLogPublisher<T extends HTTPAccessLogPublisherCfg>
+  extends HTTPAccessLogPublisher<T>
+  implements CommonAuditLogPublisher, ConfigurationChangeListener<T>
+{
+
+  /** Current configuration for this publisher. */
+  private T config;
+
+  @Override
+  public void setRequestHandler(RequestHandler handler)
+  {
+    // nothing to do
+  }
+
+  T getConfig()
+  {
+    return config;
+  }
+
+  @Override
+  public void initializeLogPublisher(final T cfg, ServerContext serverContext)
+  {
+    config = cfg;
+  }
+
+  @Override
+  public final DN getDN()
+  {
+    return config != null ? config.dn() : null;
+  }
+
+  @Override
+  public ConfigChangeResult applyConfigurationChange(final T config)
+  {
+    this.config = config;
+    return new ConfigChangeResult();
+  }
+
+  @Override
+  public boolean isConfigurationAcceptable(final T configuration,
+      final List<LocalizableMessage> unacceptableReasons)
+  {
+    return true;
+  }
+
+  @Override
+  public boolean isConfigurationChangeAcceptable(final T config, final List<LocalizableMessage> unacceptableReasons)
+  {
+    return true;
+  }
+
+  @Override
+  public void logRequestInfo(HTTPRequestInfo requestInfo)
+  {
+    // nothing to do
+  }
+
+  @Override
+  public void close()
+  {
+    // nothing to do
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditLogPublisher.java
new file mode 100644
index 0000000..72cd1b8
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditLogPublisher.java
@@ -0,0 +1,44 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import org.forgerock.json.resource.RequestHandler;
+
+/**
+ * Common interface for all log publisher that log to Common Audit.
+ */
+interface CommonAuditLogPublisher
+{
+
+  /**
+   * Sets the handler to use for publishing audit events.
+   *
+   * @param handler
+   *          The common audit handler accepting requests.
+   */
+  void setRequestHandler(RequestHandler handler);
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CsvFileAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CsvFileAccessLogPublisher.java
new file mode 100644
index 0000000..4fdacd0
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CsvFileAccessLogPublisher.java
@@ -0,0 +1,63 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import java.util.List;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.CsvFileAccessLogPublisherCfg;
+
+/**
+ * Common Audit publisher which publishes access events to CSV files.
+ */
+final class CsvFileAccessLogPublisher
+  extends CommonAuditAccessLogPublisher<CsvFileAccessLogPublisherCfg>
+  implements ConfigurationChangeListener<CsvFileAccessLogPublisherCfg>
+{
+
+  @Override
+  boolean shouldLogControlOids()
+  {
+    return getConfig().isLogControlOids();
+  }
+
+  @Override
+  public ConfigChangeResult applyConfigurationChange(final CsvFileAccessLogPublisherCfg config)
+  {
+    setConfig(config);
+    return new ConfigChangeResult();
+  }
+
+  @Override
+  public boolean isConfigurationChangeAcceptable(final CsvFileAccessLogPublisherCfg config,
+      final List<LocalizableMessage> unacceptableReasons)
+  {
+    return true;
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/ExternalAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/ExternalAccessLogPublisher.java
new file mode 100644
index 0000000..a6c2f13
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/ExternalAccessLogPublisher.java
@@ -0,0 +1,63 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import java.util.List;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.ExternalAccessLogPublisherCfg;
+
+/**
+ * Common audit publisher which publishes access events to some external
+ * publisher.
+ */
+final class ExternalAccessLogPublisher
+  extends CommonAuditAccessLogPublisher<ExternalAccessLogPublisherCfg>
+  implements ConfigurationChangeListener<ExternalAccessLogPublisherCfg>
+{
+
+  @Override
+  boolean shouldLogControlOids()
+  {
+    return getConfig().isLogControlOids();
+  }
+
+  @Override
+  public ConfigChangeResult applyConfigurationChange(final ExternalAccessLogPublisherCfg config)
+  {
+    setConfig(config);
+    return new ConfigChangeResult();
+  }
+
+  @Override
+  public boolean isConfigurationChangeAcceptable(final ExternalAccessLogPublisherCfg config,
+      final List<LocalizableMessage> unacceptableReasons)
+  {
+    return true;
+  }
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPAccessLogger.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPAccessLogger.java
index 7a04082..a7d1dd2 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPAccessLogger.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPAccessLogger.java
@@ -128,6 +128,7 @@
   public final synchronized void removeAllLogPublishers()
   {
     loggerStorage.removeAllLogPublishers();
+    getServerContext().getCommonAudit().shutdown();
   }
 
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/OpenDJAccessEventBuilder.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/OpenDJAccessEventBuilder.java
new file mode 100644
index 0000000..a4dc445
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/OpenDJAccessEventBuilder.java
@@ -0,0 +1,267 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2015 ForgeRock AS
+ */
+package org.opends.server.loggers;
+
+import static org.forgerock.json.JsonValue.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.forgerock.audit.events.AccessAuditEventBuilder;
+import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.json.JsonValue;
+import org.forgerock.util.Reject;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.types.AdditionalLogItem;
+import org.opends.server.types.Control;
+import org.opends.server.types.Operation;
+
+/**
+ * Builder for /audit/access events specific to OpenDJ. This builder add LDAP
+ * specific fields to the common fields defined in AccessAuditEventBuilder.
+ *
+ * @param <T>
+ *          This builder.
+ */
+class OpenDJAccessAuditEventBuilder<T extends OpenDJAccessAuditEventBuilder<T>> extends AccessAuditEventBuilder<T>
+{
+
+  private OpenDJAccessAuditEventBuilder()
+  {
+    super();
+  }
+
+  @SuppressWarnings("rawtypes")
+  public static <T> OpenDJAccessAuditEventBuilder<?> openDJAccessEvent()
+  {
+    return new OpenDJAccessAuditEventBuilder();
+  }
+
+  public T ldapAdditionalItems(Operation op)
+  {
+    String items = getAdditionalItemsAsString(op);
+    if (!items.isEmpty())
+    {
+      getLdapValue().put("items", items);
+    }
+    return self();
+  }
+
+  public T ldapAttr(String attr)
+  {
+    getLdapValue().put("attr", attr);
+    return self();
+  }
+
+  public T ldapConnectionId(long id)
+  {
+    getLdapValue().put("connId", id);
+    return self();
+  }
+
+  public T ldapControls(Operation operation)
+  {
+    JsonValue ldapValue = getLdapValue();
+    List<Control> requestControls = operation.getRequestControls();
+    if (!requestControls.isEmpty())
+    {
+      ldapValue.put("reqControls", getControlsAsString(requestControls));
+    }
+    List<Control> responseControls = operation.getResponseControls();
+    if (!responseControls.isEmpty())
+    {
+      ldapValue.put("respControls", getControlsAsString(responseControls));
+    }
+    return self();
+  }
+
+  public T ldapDn(String dn)
+  {
+    getLdapValue().put("dn", dn);
+    return self();
+  }
+
+  public T ldapFailureMessage(String msg)
+  {
+    getLdapValue().put("failureReason", msg);
+    return self();
+  }
+
+  public T ldapIds(Operation op)
+  {
+    JsonValue ldapValue = getLdapValue();
+    ldapValue.put("connId", op.getConnectionID());
+    ldapValue.put("msgId", op.getMessageID());
+    return self();
+  }
+
+  public T ldapIdToAbandon(int id)
+  {
+    getLdapValue().put("idToAbandon", id);
+    return self();
+  }
+
+  public T ldapMaskedResultAndMessage(Operation operation)
+  {
+    JsonValue ldapValue = getLdapValue();
+    if (operation.getMaskedResultCode() != null)
+    {
+      ldapValue.put("maskedResult", operation.getMaskedResultCode().intValue());
+    }
+    final LocalizableMessageBuilder maskedMsg = operation.getMaskedErrorMessage();
+    if (maskedMsg != null && maskedMsg.length() > 0)
+    {
+      ldapValue.put("maskedMessage", maskedMsg.toString());
+    }
+    return self();
+  }
+
+  public T ldapMessage(String msg)
+  {
+    getLdapValue().put("message", msg);
+    return self();
+  }
+
+  public T ldapName(String name)
+  {
+    getLdapValue().put("name", name);
+    return self();
+  }
+
+  public T ldapModifyDN(ModifyDNOperation modifyDNOperation)
+  {
+    JsonValue ldapValue = getLdapValue();
+    ldapValue.put("newRDN", modifyDNOperation.getRawNewRDN().toString());
+    ldapValue.put("newSup", modifyDNOperation.getRawNewSuperior().toString());
+    ldapValue.put("deleteOldRDN", modifyDNOperation.deleteOldRDN());
+    return self();
+  }
+
+  public T ldapNEntries(int nbEntries)
+  {
+    getLdapValue().put("nentries", nbEntries);
+    return self();
+  }
+
+  public T ldapOid(String oid)
+  {
+    getLdapValue().put("oid", oid);
+    return self();
+  }
+
+  public T ldapProtocolVersion(String version)
+  {
+    getLdapValue().put("version", version);
+    return self();
+  }
+
+  public T ldapReason(String msg)
+  {
+    getLdapValue().put("reason", msg);
+    return self();
+  }
+
+  public T ldapSearch(SearchOperation searchOperation)
+  {
+    JsonValue ldapValue = getLdapValue();
+    // for search base, re-uses the "dn" field
+    ldapValue.put("dn", searchOperation.getRawBaseDN().toString());
+    ldapValue.put("scope", searchOperation.getScope().toString());
+    ldapValue.put("filter", searchOperation.getRawFilter().toString());
+
+    final Set<String> attrs = searchOperation.getAttributes();
+    if ((attrs == null) || attrs.isEmpty())
+    {
+      ldapValue.put("attrs", Arrays.asList("ALL"));
+    }
+    else
+    {
+      ldapValue.put("attrs", new ArrayList<>(attrs));
+    }
+    return self();
+  }
+
+  public T ldapSync(Operation operation)
+  {
+    if (operation.isSynchronizationOperation())
+    {
+      getLdapValue().put("opType", "sync");
+    }
+    return self();
+  }
+
+  public T ldapAuthType(String type)
+  {
+    getLdapValue().put("authType", type);
+    return self();
+  }
+
+  public T runAs(String id)
+  {
+    Reject.ifNull(id);
+    jsonValue.put("runAs", id);
+    return self();
+  }
+
+  private List<String> getControlsAsString(List<Control> controls)
+  {
+    List<String> list = new ArrayList<>();
+    for (final Control control : controls)
+    {
+      list.add(control.getOID());
+    }
+    return list;
+  }
+
+  private String getAdditionalItemsAsString(Operation operation)
+  {
+    StringBuilder items = new StringBuilder();
+    for (final AdditionalLogItem item : operation.getAdditionalLogItems())
+    {
+      items.append(' ');
+      item.toString(items);
+    }
+    return items.toString();
+  }
+
+  private JsonValue getLdapValue()
+  {
+    final JsonValue ldapValue;
+    if (jsonValue.isDefined("ldap"))
+    {
+      ldapValue = jsonValue.get("ldap");
+    }
+    else
+    {
+      ldapValue = json(object());
+      jsonValue.put("ldap", ldapValue);
+    }
+    return ldapValue;
+  }
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java
index a252c8b..90c4fa8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java
@@ -42,6 +42,7 @@
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConnectionHandler;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ServerContext;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
@@ -122,7 +123,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void initializeConnectionHandler(LDIFConnectionHandlerCfg
+  public void initializeConnectionHandler(ServerContext serverContext, LDIFConnectionHandlerCfg
                                                configuration)
   {
     String ldifDirectoryPath = configuration.getLDIFDirectory();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessAuditFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessAuditFilter.java
new file mode 100644
index 0000000..83d2f26
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessAuditFilter.java
@@ -0,0 +1,169 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2013-2015 ForgeRock AS
+ */
+package org.opends.server.protocols.http;
+
+import static org.forgerock.audit.events.AccessAuditEventBuilder.accessEvent;
+import static org.forgerock.json.resource.Requests.newCreateRequest;
+import static org.forgerock.json.resource.ResourcePath.resourcePath;
+
+import java.util.concurrent.TimeUnit;
+
+import org.forgerock.audit.events.AccessAuditEventBuilder;
+import org.forgerock.http.Filter;
+import org.forgerock.http.Handler;
+import org.forgerock.http.MutableUri;
+import org.forgerock.http.protocol.Form;
+import org.forgerock.http.protocol.Request;
+import org.forgerock.http.protocol.Response;
+import org.forgerock.http.protocol.Status;
+import org.forgerock.json.resource.CreateRequest;
+import org.forgerock.json.resource.RequestHandler;
+import org.forgerock.services.context.ClientContext;
+import org.forgerock.services.context.Context;
+import org.forgerock.services.context.RequestAuditContext;
+import org.forgerock.services.context.TransactionIdContext;
+import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.ResultHandler;
+import org.forgerock.util.promise.RuntimeExceptionHandler;
+import org.forgerock.util.time.TimeService;
+
+/**
+ * This filter aims to send some access audit events to the AuditService managed as a CREST handler.
+ */
+public class CommonAuditHttpAccessAuditFilter implements Filter {
+
+    private final RequestHandler auditServiceHandler;
+    private final TimeService time;
+    private final String productName;
+
+    /**
+     * Constructs a new HttpAccessAuditFilter.
+     *
+     * @param productName The name of product generating the event.
+     * @param auditServiceHandler The {@link RequestHandler} to publish the events.
+     * @param time The {@link TimeService} to use.
+     */
+    public CommonAuditHttpAccessAuditFilter(String productName, RequestHandler auditServiceHandler, TimeService time) {
+        this.productName = productName;
+        this.auditServiceHandler = auditServiceHandler;
+        this.time = time;
+    }
+
+    @Override
+    public Promise<Response, NeverThrowsException> filter(Context context, Request request, Handler next) {
+        TransactionIdContext txContext = context.asContext(TransactionIdContext.class);
+        ClientContext clientContext = context.asContext(ClientContext.class);
+
+        AccessAuditEventBuilder<?> accessAuditEventBuilder = accessEvent();
+
+        String protocol = clientContext.isSecure() ? "HTTPS" : "HTTP";
+        accessAuditEventBuilder
+                .eventName(productName + "-" + protocol + "-ACCESS")
+                .timestamp(time.now())
+                .transactionId(txContext.getTransactionId().getValue())
+                .server(clientContext.getLocalAddress(),
+                        clientContext.getLocalPort(),
+                        clientContext.getLocalName())
+                .client(clientContext.getRemoteAddress(),
+                        clientContext.getRemotePort(),
+                        clientContext.getRemoteHost())
+                .httpRequest(clientContext.isSecure(),
+                             request.getMethod(),
+                             getRequestPath(request.getUri()),
+                             new Form().fromRequestQuery(request),
+                             request.getHeaders().copyAsMultiMapOfStrings());
+
+        try {
+            final Promise<Response, NeverThrowsException> promise;
+            promise = next.handle(context, request)
+                    .thenOnResult(onResult(context, accessAuditEventBuilder));
+            promise.thenOnRuntimeException(onRuntimeException(context, accessAuditEventBuilder));
+            return promise;
+        } catch (RuntimeException re) {
+            onRuntimeException(context, accessAuditEventBuilder).handleRuntimeException(re);
+            throw re;
+        }
+    }
+
+    // See HttpContext.getRequestPath
+    private String getRequestPath(MutableUri uri) {
+        return new StringBuilder()
+            .append(uri.getScheme())
+            .append("://")
+            .append(uri.getRawAuthority())
+            .append(uri.getRawPath()).toString();
+    }
+
+    private ResultHandler<? super Response> onResult(final Context context,
+                                                     final AccessAuditEventBuilder<?> accessAuditEventBuilder) {
+        return new ResultHandler<Response>() {
+            @Override
+            public void handleResult(Response response) {
+                sendAuditEvent(response, context, accessAuditEventBuilder);
+            }
+
+        };
+    }
+
+    private RuntimeExceptionHandler onRuntimeException(final Context context,
+                                                       final AccessAuditEventBuilder<?> accessAuditEventBuilder) {
+        return new RuntimeExceptionHandler() {
+            @Override
+            public void handleRuntimeException(RuntimeException exception) {
+                // TODO How to be sure that the final status code sent back with the response will be a 500 ?
+                Response response = new Response(Status.INTERNAL_SERVER_ERROR);
+                sendAuditEvent(response, context, accessAuditEventBuilder);
+            }
+        };
+    }
+
+    private void sendAuditEvent(final Response response,
+                                final Context context,
+                                final AccessAuditEventBuilder<?> accessAuditEventBuilder) {
+        RequestAuditContext requestAuditContext = context.asContext(RequestAuditContext.class);
+        long elapsedTime = time.now() - requestAuditContext.getRequestReceivedTime();
+        accessAuditEventBuilder.httpResponse(response.getHeaders().copyAsMultiMapOfStrings());
+        accessAuditEventBuilder.response(mapResponseStatus(response.getStatus()),
+                                         String.valueOf(response.getStatus().getCode()),
+                                         elapsedTime,
+                                         TimeUnit.MILLISECONDS);
+
+        CreateRequest request =
+            newCreateRequest(resourcePath("/http-access"), accessAuditEventBuilder.toEvent().getValue());
+        auditServiceHandler.handleCreate(context, request);
+    }
+
+    private static AccessAuditEventBuilder.ResponseStatus mapResponseStatus(Status status) {
+        switch(status.getFamily()) {
+        case CLIENT_ERROR:
+        case SERVER_ERROR:
+            return AccessAuditEventBuilder.ResponseStatus.FAILED;
+        default:
+            return AccessAuditEventBuilder.ResponseStatus.SUCCESSFUL;
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessCheckEnabledFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessCheckEnabledFilter.java
new file mode 100644
index 0000000..47e3024
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditHttpAccessCheckEnabledFilter.java
@@ -0,0 +1,68 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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 2013-2015 ForgeRock AS
+ */
+package org.opends.server.protocols.http;
+
+import org.forgerock.http.Filter;
+import org.forgerock.http.Handler;
+import org.forgerock.http.protocol.Request;
+import org.forgerock.http.protocol.Response;
+import org.forgerock.services.context.Context;
+import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.opends.server.core.ServerContext;
+
+/**
+ * Filter that checks if at least one HTTP access logger is enabled for common audit, and short-circuit
+ * the corresponding filter if this is not the case.
+ */
+class CommonAuditHttpAccessCheckEnabledFilter implements Filter
+{
+
+  private final ServerContext serverContext;
+
+  /** The HTTP access audit filter to go through if HTTP access logger is enabled. */
+  private final Filter httpAccessAuditFilter;
+
+  CommonAuditHttpAccessCheckEnabledFilter(ServerContext serverContext, Filter httpAccessAuditFilter)
+  {
+    this.serverContext = serverContext;
+    this.httpAccessAuditFilter = httpAccessAuditFilter;
+  }
+
+  @Override
+  public Promise<Response, NeverThrowsException> filter(
+      final Context context, final Request request, final Handler next)
+  {
+    if (serverContext.getCommonAudit().isHttpAccessLogEnabled())
+    {
+      // introduce HttpAccessAuditFilter into the filter chain
+      return httpAccessAuditFilter.filter(context, request, next);
+    }
+    // avoid HttpAccessAuditFilter, follow the filter chain
+    return next.handle(context, request);
+  }
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
index aaaef27..ed36968 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
@@ -36,6 +36,7 @@
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+
 import java.io.IOException;
 import java.net.InetAddress;
 import java.util.Arrays;
@@ -80,6 +81,7 @@
 import org.opends.server.api.ServerShutdownListener;
 import org.opends.server.api.TrustManagerProvider;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ServerContext;
 import org.opends.server.extensions.NullKeyManagerProvider;
 import org.opends.server.extensions.NullTrustManagerProvider;
 import org.opends.server.loggers.HTTPAccessLogger;
@@ -162,6 +164,8 @@
   /** The SSL engine configurator is used for obtaining default SSL parameters. */
   private SSLEngineConfigurator sslEngineConfigurator;
 
+  private ServerContext serverContext;
+
   /** Default constructor. It is invoked by reflection to create this {@link ConnectionHandler}. */
   public HTTPConnectionHandler()
   {
@@ -419,9 +423,10 @@
   }
 
   @Override
-  public void initializeConnectionHandler(HTTPConnectionHandlerCfg config)
+  public void initializeConnectionHandler(ServerContext serverContext, HTTPConnectionHandlerCfg config)
       throws ConfigException, InitializationException
   {
+    this.serverContext = serverContext;
     this.enabled = config.isEnabled();
 
     if (friendlyName == null)
@@ -782,7 +787,8 @@
   {
     // Create and deploy the Web app context
     final WebappContext ctx = new WebappContext(servletName);
-    ctx.addServlet(servletName, new HttpFrameworkServlet(new LdapHttpApplication(this))).addMapping(urlPatterns);
+    ctx.addServlet(servletName,
+        new HttpFrameworkServlet(new LdapHttpApplication(serverContext, this))).addMapping(urlPatterns);
     ctx.deploy(this.httpServer);
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
index 0850d8c..0dd19b6 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
@@ -34,6 +34,7 @@
 import org.forgerock.http.Handler;
 import org.forgerock.http.HttpApplication;
 import org.forgerock.http.HttpApplicationException;
+import org.forgerock.http.filter.TransactionIdInboundFilter;
 import org.forgerock.http.handler.Handlers;
 import org.forgerock.http.io.Buffer;
 import org.forgerock.http.protocol.Request;
@@ -57,7 +58,10 @@
 import org.forgerock.util.Factory;
 import org.forgerock.util.promise.NeverThrowsException;
 import org.forgerock.util.promise.Promise;
+import org.forgerock.util.time.TimeService;
 import org.opends.messages.ProtocolMessages;
+import org.opends.server.core.ServerContext;
+import org.opends.server.util.DynamicConstants;
 
 /** Main class of the HTTP Connection Handler web application */
 class LdapHttpApplication implements HttpApplication
@@ -115,9 +119,11 @@
   private HTTPConnectionHandler connectionHandler;
   private LdapHttpHandler handler;
   private CollectClientConnectionsFilter filter;
+  private final ServerContext serverContext;
 
-  LdapHttpApplication(HTTPConnectionHandler connectionHandler)
+  LdapHttpApplication(ServerContext serverContext, HTTPConnectionHandler connectionHandler)
   {
+    this.serverContext = serverContext;
     this.connectionHandler = connectionHandler;
   }
 
@@ -132,7 +138,15 @@
       handler = new LdapHttpHandler(configuration);
       filter = new CollectClientConnectionsFilter(connectionHandler, getAuthenticationConfig(configuration));
       configuration.verifyAllKeysAccessed();
-      return Handlers.chainOf(handler, filter);
+
+      TransactionIdInboundFilter transactionIdFilter = new TransactionIdInboundFilter();
+      RequestHandler requestHandler = serverContext.getCommonAudit().getAuditServiceForHttpAccessLog();
+      CommonAuditHttpAccessAuditFilter httpAccessFilter =
+          new CommonAuditHttpAccessAuditFilter(DynamicConstants.PRODUCT_NAME, requestHandler, TimeService.SYSTEM);
+      CommonAuditHttpAccessCheckEnabledFilter checkFilter =
+          new CommonAuditHttpAccessCheckEnabledFilter(serverContext, httpAccessFilter);
+
+      return Handlers.chainOf(handler, transactionIdFilter, checkFilter, filter);
     }
     catch (final Exception e)
     {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/internal/InternalConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/internal/InternalConnectionHandler.java
index 377cc06..2a346d3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/internal/InternalConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/internal/InternalConnectionHandler.java
@@ -29,12 +29,14 @@
 
 
 
+
 import java.util.Collection;
 import java.util.LinkedList;
 
 import org.opends.server.admin.std.server.*;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConnectionHandler;
+import org.opends.server.core.ServerContext;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.types.DN;
 import org.opends.server.types.InitializationException;
@@ -108,6 +110,7 @@
    * Initializes this connection handler provider based on the
    * information in the provided connection handler configuration.
    *
+   * @param  serverContext  The server context.
    * @param  configuration  The connection handler configuration that
    *                        contains the information to use to
    *                        initialize this connection handler.
@@ -123,8 +126,7 @@
    *                                   configuration.
    */
   @Override
-  public void initializeConnectionHandler(
-                   ConnectionHandlerCfg configuration)
+  public void initializeConnectionHandler(ServerContext serverContext, ConnectionHandlerCfg configuration)
       throws ConfigException, InitializationException
   {
     this.configuration = configuration;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/JmxConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/JmxConnectionHandler.java
index 8e1201e..2f33cab 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/JmxConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -49,6 +49,7 @@
 import org.opends.server.api.ConnectionHandler;
 import org.opends.server.api.ServerShutdownListener;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ServerContext;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.HostPort;
@@ -299,7 +300,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void initializeConnectionHandler(JMXConnectionHandlerCfg config)
+  public void initializeConnectionHandler(ServerContext serverContext, JMXConnectionHandlerCfg config)
          throws ConfigException, InitializationException
   {
     // Configuration is ok.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index b358ea2..032a100 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -58,6 +58,7 @@
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.PluginConfigManager;
 import org.opends.server.core.QueueingStrategy;
+import org.opends.server.core.ServerContext;
 import org.opends.server.core.WorkQueueStrategy;
 import org.opends.server.extensions.NullKeyManagerProvider;
 import org.opends.server.extensions.NullTrustManagerProvider;
@@ -642,7 +643,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void initializeConnectionHandler(LDAPConnectionHandlerCfg config)
+  public void initializeConnectionHandler(ServerContext serverContext, LDAPConnectionHandlerCfg config)
       throws ConfigException, InitializationException
   {
     if (friendlyName == null)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/ServerConstants.java b/opendj-server-legacy/src/main/java/org/opends/server/util/ServerConstants.java
index 825edbb..9e34a29 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/ServerConstants.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/ServerConstants.java
@@ -2305,7 +2305,10 @@
   public static final String OID_SUBTREE_DELETE_CONTROL =
        "1.2.840.113556.1.4.805";
 
-
+  /**
+   * The OID for the transactionId control.
+   */
+  public static final String OID_TRANSACTION_ID_CONTROL = "1.3.6.1.4.1.36733.2.1.5.1";
 
   /**
    * The OID for the paged results control defined in RFC 2696.
diff --git a/opendj-server-legacy/src/main/resources/org/opends/server/loggers/audit-config.json b/opendj-server-legacy/src/main/resources/org/opends/server/loggers/audit-config.json
new file mode 100644
index 0000000..f010de4
--- /dev/null
+++ b/opendj-server-legacy/src/main/resources/org/opends/server/loggers/audit-config.json
@@ -0,0 +1,402 @@
+{
+  "additionalTopics" : {
+      "http-access": {
+        "schema": {
+          "$schema": "http://json-schema.org/draft-04/schema#",
+          "id": "/",
+          "type": "object",
+          "properties": {
+            "_id": {
+              "description": "org.forgerock.audit.events.access.id",
+              "type": "string"
+            },
+            "timestamp": {
+              "description": "org.forgerock.audit.events.access.timestamp",
+              "type": "string"
+            },
+            "eventName": {
+              "description": "org.forgerock.audit.events.access.eventName",
+              "type": "string"
+            },
+            "transactionId": {
+              "description": "org.forgerock.audit.events.access.transactionId",
+              "type": "string"
+            },
+            "userId": {
+              "description": "org.forgerock.audit.events.access.userId",
+              "type": "string"
+            },
+            "trackingIds": {
+              "description": "org.forgerock.audit.events.access.trackingIds",
+              "type": "array",
+              "items": {
+                "id": "0",
+                "type": "string"
+              }
+            },
+            "server": {
+              "type": "object",
+              "properties": {
+                "ip": {
+                  "description": "org.forgerock.audit.events.access.server.ip",
+                  "type": "string"
+                },
+                "port": {
+                  "description": "org.forgerock.audit.events.access.server.port",
+                  "type": "string"
+                }
+              }
+            },
+            "client": {
+              "type": "object",
+              "properties": {
+                "host": {
+                  "description": "org.forgerock.audit.events.access.client.host",
+                  "type": "string"
+                },
+                "ip": {
+                  "description": "org.forgerock.audit.events.access.client.ip",
+                  "type": "string"
+                },
+                "port": {
+                  "description": "org.forgerock.audit.events.access.client.port",
+                  "type": "string"
+                }
+              }
+            },
+            "request": {
+              "type": "object",
+              "properties": {
+                "protocol": {
+                  "description": "org.forgerock.audit.events.access.request.protocol",
+                  "type": "string"
+                },
+                "operation": {
+                  "description": "org.forgerock.audit.events.access.request.operation",
+                  "type": "string"
+                },
+                "detail": {
+                  "description": "org.forgerock.audit.events.access.request.detail",
+                  "type": "object"
+                }
+              }
+            },
+            "http": {
+              "type": "object",
+              "properties": {
+                "request": {
+                  "description": "org.forgerock.audit.events.access.http.request",
+                  "type": "object",
+                  "properties": {
+                    "secure": {
+                      "description": "org.forgerock.audit.events.access.http.secure",
+                      "type": "boolean"
+                    },
+                    "method": {
+                      "description": "org.forgerock.audit.events.access.http.method",
+                      "type": "string"
+                    },
+                    "path": {
+                      "description": "org.forgerock.audit.events.access.http.path",
+                      "type": "string"
+                    },
+                    "queryParameters": {
+                      "description": "org.forgerock.audit.events.access.http.queryParameters",
+                      "type": "object",
+                      "additionalProperties": {
+                        "type": "array",
+                        "items": {
+                          "type": "string"
+                        }
+                      }
+                    },
+                    "headers": {
+                      "description": "org.forgerock.audit.events.access.http.headers",
+                      "type": "object",
+                      "additionalProperties": {
+                        "type": "array",
+                        "items": {
+                          "type": "string"
+                        }
+                      }
+                    },
+                    "cookies": {
+                      "description": "org.forgerock.audit.events.access.http.cookies",
+                      "type": "object",
+                      "additionalProperties": {
+                        "type": "string"
+                      }
+                    }
+                  }
+                },
+                "response": {
+                  "description": "org.forgerock.audit.events.access.http.response",
+                  "type": "object",
+                  "properties": {
+                    "headers": {
+                      "description": "org.forgerock.audit.events.access.http.request.headers",
+                      "type": "object",
+                      "additionalProperties": {
+                        "type": "array",
+                        "items": {
+                          "type": "string"
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            },
+            "response": {
+              "type": "object",
+              "properties": {
+                "status": {
+                  "description": "org.forgerock.audit.events.access.response.status",
+                  "type": "string"
+                },
+                "statusCode": {
+                  "description": "org.forgerock.audit.events.access.response.statusCode",
+                  "type": "string"
+                },
+                "detail": {
+                  "description": "org.forgerock.audit.events.access.response.detail",
+                  "type": "string"
+                },
+                "elapsedTime": {
+                  "description": "org.forgerock.audit.events.access.response.elapsedTime",
+                  "type": "integer"
+                },
+                "elapsedTimeUnits": {
+                  "description": "org.forgerock.audit.events.access.response.elapsedTimeUnits",
+                  "type": "string"
+                }
+              }
+            }
+          }
+        }
+      },
+      "ldap-access": {
+        "schema": {
+          "$schema": "http://json-schema.org/draft-04/schema#",
+          "id": "/",
+          "type": "object",
+          "properties": {
+            "_id": {
+              "description": "org.forgerock.audit.events.access.id",
+              "type": "string"
+            },
+            "timestamp": {
+              "description": "org.forgerock.audit.events.access.timestamp",
+              "type": "string"
+            },
+            "eventName": {
+              "description": "org.forgerock.audit.events.access.eventName",
+              "type": "string"
+            },
+            "transactionId": {
+              "description": "org.forgerock.audit.events.access.transactionId",
+              "type": "string"
+            },
+            "userId": {
+              "description": "org.forgerock.audit.events.access.userId",
+              "type": "string"
+            },
+            "runAs": {
+              "description": "org.forgerock.audit.events.activity.runAs",
+              "type": "string"
+            },
+            "server": {
+              "type": "object",
+              "properties": {
+                "ip": {
+                  "description": "org.forgerock.audit.events.access.server.ip",
+                  "type": "string"
+                },
+                "port": {
+                  "description": "org.forgerock.audit.events.access.server.port",
+                  "type": "string"
+                }
+              }
+            },
+            "client": {
+              "type": "object",
+              "properties": {
+                "host": {
+                  "description": "org.forgerock.audit.events.access.client.host",
+                  "type": "string"
+                },
+                "ip": {
+                  "description": "org.forgerock.audit.events.access.client.ip",
+                  "type": "string"
+                },
+                "port": {
+                  "description": "org.forgerock.audit.events.access.client.port",
+                  "type": "string"
+                }
+              }
+            },
+            "request": {
+              "type": "object",
+              "properties": {
+                "protocol": {
+                  "description": "org.forgerock.audit.events.access.request.protocol",
+                  "type": "string"
+                },
+                "operation": {
+                  "description": "org.forgerock.audit.events.access.request.operation",
+                  "type": "string"
+                }
+              }
+            },
+            "response": {
+              "type": "object",
+              "properties": {
+                "status": {
+                  "description": "org.forgerock.audit.events.access.response.status",
+                  "type": "string"
+                },
+                "statusCode": {
+                  "description": "org.forgerock.audit.events.access.response.statusCode",
+                  "type": "string"
+                },
+                "detail": {
+                  "description": "org.forgerock.audit.events.access.response.detail",
+                  "type": "string"
+                },
+                "elapsedTime": {
+                  "description": "org.forgerock.audit.events.access.response.elapsedTime",
+                  "type": "integer"
+                },
+                "elapsedTimeUnits": {
+                  "description": "org.forgerock.audit.events.access.response.elapsedTimeUnits",
+                  "type": "string"
+                }
+              }
+            },
+            "ldap": {
+                  "id": "ldap",
+                  "type": "object",
+                  "properties": {
+                    "connId": {
+                      "id": "connId",
+                      "type": "string"
+                    },
+                    "msgId": {
+                      "id": "msgId",
+                      "type": "string"
+                    },
+                    "dn": {
+                      "id": "dn",
+                      "type": "string"
+                    },
+                    "scope": {
+                      "id": "scope",
+                      "type": "string"
+                    },
+                    "filter": {
+                      "id": "filter",
+                      "type": "string"
+                    },
+                    "attrs": {
+                      "id": "attrs",
+                      "type": "array",
+                      "items": {
+                        "type": "string"
+                      }
+                    },
+                    "nentries": {
+                      "id": "nentries",
+                      "type": "string"
+                    },
+                    "authType": {
+                      "id": "authType",
+                      "type": "string"
+                    },
+                    "reqControls": {
+                      "id": "reqControls",
+                      "type": "array",
+                      "items": {
+                        "type": "string"
+                      }
+                    },
+                    "respControls": {
+                      "id": "respControls",
+                      "type": "array",
+                      "items": {
+                        "type": "string"
+                      }
+                    },
+                    "additionalItems": {
+                      "id": "additionalItems",
+                      "type": "string"
+                    },
+                    "items" : {
+                      "id" : "items",
+                      "type" : "string"  
+                    },
+                    "attr" : {
+                      "id" : "attr",
+                      "type" : "string"
+                    },
+                    "failureReason" : {
+                      "id" : "failureReason",
+                      "type" : "string"
+                    },
+                    "idToAbandon" : {
+                      "id" : "idToAbandon",
+                      "type" : "integer"
+                    },
+                    "maskedResult" : {
+                      "id" : "maskedResult",
+                      "type" : "integer"
+                    },
+                    "maskedMessage" : {
+                      "id" : "maskedMessage",
+                      "type" : "string"
+                    },
+                     "message" : {
+                      "id" : "message",
+                      "type" : "string"
+                    },
+                     "name" : {
+                      "id" : "name",
+                      "type" : "string"
+                    },
+                     "newRDN" : {
+                      "id" : "newRDN",
+                      "type" : "string"
+                    },
+                     "newSup" : {
+                      "id" : "newSup",
+                      "type" : "string"
+                    },
+                     "deleteOldRDN" : {
+                      "id" : "deleteOldRDN",
+                      "type" : "boolean"
+                    },
+                     "oid" : {
+                      "id" : "oid",
+                      "type" : "string"
+                    },
+                     "version" : {
+                      "id" : "version",
+                      "type" : "string"
+                    },
+                     "reason" : {
+                      "id" : "reason",
+                      "type" : "string"
+                    },
+                    "opType": {
+                      "id": "opType",
+                      "type": "string"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/config.properties b/opendj-server-legacy/src/messages/org/opends/messages/config.properties
index 0d138a9..2123ab5 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/config.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/config.properties
@@ -942,3 +942,9 @@
 WARN_CONFIG_LOGGING_UNSUPPORTED_FIELDS_IN_LOG_FORMAT_734=The log format \
  for %s contains the folowing unsupported fields: %s. Their output will be \
  replaced with a dash ("-") character
+ERR_CONFIG_LOGGER_CANNOT_UPDATE_LOGGER_735=An error occurred while \
+ attempting to update a Directory Server logger from the information in \
+ configuration entry %s: %s
+ERR_CONFIG_LOGGER_CANNOT_DELETE_LOGGER_736=An error occurred while \
+ attempting to delete a Directory Server logger from the information in \
+ configuration entry %s: %s
\ No newline at end of file
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/logger.properties b/opendj-server-legacy/src/messages/org/opends/messages/logger.properties
index 8625a26..658cb57 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/logger.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/logger.properties
@@ -69,3 +69,34 @@
  free disk space in the partition containing log file %s: %s
 ERR_LOGGER_ERROR_ENFORCING_RETENTION_POLICY_12=Error occurred while \
  enforcing retention policy %s for logger %s: %s
+ERR_COMMON_AUDIT_CREATE_13=Error occurred while creating common audit \
+ facility: %s 
+ERR_COMMON_AUDIT_ADD_OR_UPDATE_LOG_PUBLISHER_14=Error while creating \
+ or updating common audit log publisher %s: %s
+ERR_COMMON_AUDIT_REMOVE_LOG_PUBLISHER_15=Error while removing common audit log \
+ publisher %s: %s
+ERR_COMMON_AUDIT_UNSUPPORTED_HANDLER_TYPE_16=Error while adding common audit log \
+ publisher %s, the publisher has an unsupported handler type
+ERR_COMMON_AUDIT_EXTERNAL_HANDLER_JSON_FILE_17=Error while reading \
+ JSON configuration file %s while creating common audit external log publisher %s: %s
+ERR_COMMON_AUDIT_EXTERNAL_HANDLER_CREATION_18=Error while creating \
+ common audit external log publisher %s: %s
+ERR_COMMON_AUDIT_CSV_HANDLER_CREATION_19=Error while creating \
+ CSV log publisher %s: %s
+ERR_COMMON_AUDIT_UNSUPPORTED_LOG_ROTATION_POLICY_20=Error while adding common audit \
+ CSV log publisher %s, the publisher defines an unsupported log rotation policy %s
+ERR_COMMON_AUDIT_UNSUPPORTED_LOG_RETENTION_POLICY_21=Error while adding common audit \
+ CSV log publisher %s, the publisher defines an unsupported log retention policy %s
+ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER_22=Error while processing common audit \
+ log publisher %s, this type of log publisher is unsupported
+ERR_COMMON_AUDIT_CSV_HANDLER_DELIMITER_CHAR_23=Error while processing common audit \
+ log publisher %s, delimiter char '%s' should not contains more than one character
+ERR_COMMON_AUDIT_CSV_HANDLER_QUOTE_CHAR_24=Error while processing common audit \
+ log publisher %s, quote char '%s' should not contains more than one character
+ERR_COMMON_AUDIT_INVALID_TIME_OF_DAY_25=Error while processing common audit \
+ log publisher %s, time of the day value '%s' for fixed time log rotation policy \
+ is not valid, it should use a 24-hour format "HHmm" : %s
+ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID_26=Error while decoding a transaction id control \
+ received from a request: %s
+ERR_COMMON_AUDIT_UNABLE_TO_PROCESS_LOG_EVENT_27=Error while processing a log event \
+ for common audit: %s
\ No newline at end of file
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties b/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
index 9560963..92e750d 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
@@ -917,3 +917,5 @@
 ERR_INVALID_KEYSTORE_1527=No usable key was found for '%s'. Verify the keystore content
 INFO_DISABLE_CONNECTION_1528=Disabling %s
 ERR_INITIALIZE_HTTP_CONNECTION_HANDLER_1529=Failed to initialize Http Connection Handler
+ERR_TRANSACTION_ID_CONTROL_HAS_NO_VALUE_1530=No value was provided for the transaction \
+ id control, whereas an UTF-8 encoded value is expected
\ No newline at end of file
diff --git a/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPConnectionHandler.java b/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPConnectionHandler.java
index 612fbf0..01ae2f6 100644
--- a/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPConnectionHandler.java
+++ b/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPConnectionHandler.java
@@ -47,6 +47,7 @@
 import org.opends.server.admin.std.server.SNMPConnectionHandlerCfg;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ServerContext;
 import org.opends.server.types.InitializationException;
 
 import static org.opends.messages.ProtocolMessages.*;
@@ -95,8 +96,8 @@
     /**
      * {@inheritDoc}
      */
-    public void initializeConnectionHandler(
-            SNMPConnectionHandlerCfg configuration)
+    @Override
+    public void initializeConnectionHandler(ServerContext serverContext, SNMPConnectionHandlerCfg configuration)
             throws ConfigException, InitializationException {
 
         if (configuration == null) {
@@ -207,6 +208,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isConfigurationChangeAcceptable(
             SNMPConnectionHandlerCfg configuration,
             List<LocalizableMessage> unacceptableReasons) {
@@ -217,6 +219,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public ConfigChangeResult applyConfigurationChange(
             SNMPConnectionHandlerCfg configuration) {
         if ((this.isOperational) && (this.provider!=null)){
@@ -228,6 +231,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public DN getComponentEntryDN() {
         return this.currentConfig.dn();
     }
@@ -235,6 +239,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public String getClassName() {
         return SNMPConnectionHandler.class.getName();
     }
@@ -242,6 +247,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LinkedHashMap<String, String> getAlerts() {
         LinkedHashMap<String, String> alerts =
           new LinkedHashMap<String, String>();
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/protocols/internal/InternalConnectionHandlerTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/protocols/internal/InternalConnectionHandlerTestCase.java
index a58dc48..06c961d 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/protocols/internal/InternalConnectionHandlerTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/protocols/internal/InternalConnectionHandlerTestCase.java
@@ -28,11 +28,13 @@
 
 
 
+import static org.mockito.Mockito.mock;
+
 import java.util.Collection;
 
 import org.testng.annotations.Test;
-
 import org.opends.server.api.ClientConnection;
+import org.opends.server.core.ServerContext;
 
 import static org.testng.Assert.*;
 
@@ -57,7 +59,7 @@
     InternalConnectionHandler handler = InternalConnectionHandler.getInstance();
     assertNotNull(handler);
 
-    handler.initializeConnectionHandler(null);
+    handler.initializeConnectionHandler(mock(ServerContext.class), null);
   }
 
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/protocols/ldap/LdapTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/protocols/ldap/LdapTestCase.java
index ca16b5b..bf328a0 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/protocols/ldap/LdapTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/protocols/ldap/LdapTestCase.java
@@ -26,6 +26,8 @@
  */
 package org.opends.server.protocols.ldap ;
 
+import static org.mockito.Mockito.mock;
+
 import static org.opends.server.config.ConfigConstants.*;
 
 import java.util.Iterator;
@@ -36,6 +38,7 @@
 import org.opends.server.admin.server.AdminTestCaseUtils;
 import org.opends.server.admin.std.meta.LDAPConnectionHandlerCfgDefn;
 import org.opends.server.admin.std.server.LDAPConnectionHandlerCfg;
+import org.opends.server.core.ServerContext;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.Attributes;
@@ -112,7 +115,7 @@
     handlerEntry.addAttribute(a, null);
     LDAPConnectionHandlerCfg config = getConfiguration(handlerEntry);
     LDAPConnectionHandler handler = new LDAPConnectionHandler();
-    handler.initializeConnectionHandler(config);
+    handler.initializeConnectionHandler(mock(ServerContext.class), config);
     return handler;
   }
 

--
Gitblit v1.10.0