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

Fabio Pistolesi
23.08.2016 470c3ddb9159d6e0b0a9d31af28e8ed46d570db6
OPENDJ-3313 Add Json handler log publisher in dsconfig

Json logger can be configured from dsconfig, same as CSV and Text loggers.
3 files modified
3 files added
720 ■■■■ changed files
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/JsonFileAccessLogPublisherConfiguration.xml 142 ●●●●● patch | view | raw | blame | history
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/JsonFileHTTPAccessLogPublisherConfiguration.xml 124 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/resource/schema/02-config.ldif 17 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java 374 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/loggers/JsonFileAccessLogPublisher.java 52 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/logger.properties 11 ●●●●● patch | view | raw | blame | history
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/JsonFileAccessLogPublisherConfiguration.xml
New file
@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  -->
<adm:managed-object name="json-file-access-log-publisher"
  plural-name="json-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 Json files.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-json-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.JsonFileAccessLogPublisher
        </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="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:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/JsonFileHTTPAccessLogPublisherConfiguration.xml
New file
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  -->
<adm:managed-object name="json-file-http-access-log-publisher"
  plural-name="json-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 access messages to Json files.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-json-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="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:managed-object>
opendj-server-legacy/resource/schema/02-config.ldif
@@ -6014,3 +6014,20 @@
  SUP ds-cfg-http-endpoint
  STRUCTURAL
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.45
  NAME 'ds-cfg-json-file-access-log-publisher'
  SUP ds-cfg-access-log-publisher
  STRUCTURAL
  MUST ( ds-cfg-log-directory )
  MAY ( ds-cfg-log-control-oids $
        ds-cfg-rotation-policy $
        ds-cfg-retention-policy )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.46
  NAME 'ds-cfg-json-file-http-access-log-publisher'
  SUP ds-cfg-http-access-log-publisher
  STRUCTURAL
  MUST ( ds-cfg-log-directory )
  MAY ( ds-cfg-rotation-policy $
        ds-cfg-retention-policy )
  X-ORIGIN 'OpenDJ Directory Server' )
opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
@@ -48,6 +48,7 @@
import org.forgerock.audit.AuditServiceProxy;
import org.forgerock.audit.DependencyProvider;
import org.forgerock.audit.events.EventTopicsMetaData;
import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration;
import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRetention;
import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRotation;
import org.forgerock.audit.filter.FilterPolicy;
@@ -56,6 +57,8 @@
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.handlers.json.JsonAuditEventHandler;
import org.forgerock.audit.handlers.json.JsonAuditEventHandlerConfiguration;
import org.forgerock.audit.json.AuditJsonConfig;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.json.JsonValue;
@@ -63,7 +66,6 @@
import org.forgerock.opendj.config.ConfigurationFramework;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.schema.ObjectClass;
import org.forgerock.opendj.server.config.server.CsvFileAccessLogPublisherCfg;
import org.forgerock.opendj.server.config.server.CsvFileHTTPAccessLogPublisherCfg;
import org.forgerock.opendj.server.config.server.ExternalAccessLogPublisherCfg;
@@ -71,15 +73,15 @@
import org.forgerock.opendj.server.config.server.FileCountLogRetentionPolicyCfg;
import org.forgerock.opendj.server.config.server.FixedTimeLogRotationPolicyCfg;
import org.forgerock.opendj.server.config.server.FreeDiskSpaceLogRetentionPolicyCfg;
import org.forgerock.opendj.server.config.server.JsonFileAccessLogPublisherCfg;
import org.forgerock.opendj.server.config.server.JsonFileHTTPAccessLogPublisherCfg;
import org.forgerock.opendj.server.config.server.LogPublisherCfg;
import org.forgerock.opendj.server.config.server.LogRetentionPolicyCfg;
import org.forgerock.opendj.server.config.server.LogRotationPolicyCfg;
import org.forgerock.opendj.server.config.server.SizeLimitLogRetentionPolicyCfg;
import org.forgerock.opendj.server.config.server.SizeLimitLogRotationPolicyCfg;
import org.forgerock.opendj.server.config.server.TimeLimitLogRotationPolicyCfg;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ServerContext;
import org.opends.server.types.Entry;
import org.opends.server.util.StaticUtils;
/**
@@ -191,7 +193,7 @@
   */
  public RequestHandler getRequestHandler(LogPublisherCfg config) throws ConfigException
  {
    if (new PublisherConfig(serverContext, config).isHttpAccessLog())
    if (new PublisherConfig(serverContext, config).logType.isHttp())
    {
      return httpAccessAuditService;
    }
@@ -215,7 +217,7 @@
      {
        final PublisherConfig newPublisher = new PublisherConfig(serverContext, newConfig);
        String normalizedName = getConfigNormalizedName(newConfig);
        if (newPublisher.isHttpAccessLog())
        if (newPublisher.logType.isHttp())
        {
          // if an old version exists, it is replaced by the new one
          httpAccessPublishers.put(normalizedName, newPublisher);
@@ -397,7 +399,7 @@
  /**
   * Build filter policies at the AuditService level to prevent logging of the headers for HTTP requests.
   * <p>
   * HTTP Headers may contains authentication information.
   * HTTP Headers may contain authentication information.
   */
  private Map<String, FilterPolicy> getFilterPoliciesToPreventHttpHeadersLogging()
  {
@@ -410,16 +412,18 @@
  private void addHandlerToBuilder(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
  {
    if (publisher.isCsv())
    switch (publisher.auditType)
    {
    case CSV:
      addCsvHandler(publisher, builder);
    }
    else if (publisher.isExternal())
    {
      break;
    case JSON:
      addJsonHandler(publisher, builder);
      break;
    case EXTERNAL:
      addExternalHandler(publisher, builder);
    }
    else
    {
      break;
    default:
      throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_HANDLER_TYPE.get(publisher.getDn()));
    }
  }
@@ -446,27 +450,26 @@
  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.setName(publisher.getName());
      csvConfig.setTopics(Collections.singleton(publisher.getCommonAuditTopic()));
      addCsvHandlerFormattingConfig(config, csvConfig);
      addCsvHandlerBufferingConfig(config, csvConfig);
      addCsvHandlerSecureConfig(publisher, config, csvConfig);
      addCsvHandlerRotationConfig(publisher, config, csvConfig);
      addCsvHandlerRetentionConfig(publisher, config, csvConfig);
      addHandlerRotationConfig(publisher, config, csvConfig);
      addHandlerRetentionConfig(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);
      throw new ConfigException(ERR_COMMON_AUDIT_FILE_BASED_HANDLER_CREATION.get(publisher.getDn(), e), e);
    }
  }
@@ -507,8 +510,36 @@
    }
  }
  private void addCsvHandlerRotationConfig(PublisherConfig publisher, CsvConfigData config,
      CsvAuditEventHandlerConfiguration auditConfig) throws ConfigException
  private void addJsonHandler(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
  {
    try
    {
      JsonConfigData config = publisher.getJsonConfig();
      JsonAuditEventHandlerConfiguration jsonConfig = new JsonAuditEventHandlerConfiguration();
      File logDirectory = getFileForPath(config.getLogDirectory());
      jsonConfig.setLogDirectory(logDirectory.getAbsolutePath());
      jsonConfig.setName(publisher.getName());
      jsonConfig.setTopics(Collections.singleton(publisher.getCommonAuditTopic()));
      addJsonHandlerBufferingConfig(config, jsonConfig);
      addHandlerRetentionConfig(publisher, config, jsonConfig);
      addHandlerRotationConfig(publisher, config, jsonConfig);
      builder.withAuditEventHandler(JsonAuditEventHandler.class, jsonConfig);
    }
    catch (Exception e)
    {
      throw new ConfigException(ERR_COMMON_AUDIT_FILE_BASED_HANDLER_CREATION.get(publisher.getDn(), e), e);
    }
  }
  private void addJsonHandlerBufferingConfig(JsonConfigData config, JsonAuditEventHandlerConfiguration auditConfig)
  {
    JsonAuditEventHandlerConfiguration.EventBufferingConfiguration jsonBufferingConfig =
        new JsonAuditEventHandlerConfiguration.EventBufferingConfiguration();
  }
  private void addHandlerRotationConfig(PublisherConfig publisher, HandlerConfigData config,
      FileBasedEventHandlerConfiguration auditConfig) throws ConfigException
  {
    SortedSet<String> rotationPolicies = config.getRotationPolicies();
    if (rotationPolicies.isEmpty())
@@ -544,8 +575,8 @@
    auditConfig.setFileRotation(fileRotation);
  }
  private void addCsvHandlerRetentionConfig(PublisherConfig publisher, CsvConfigData config,
      CsvAuditEventHandlerConfiguration auditConfig) throws ConfigException
  private void addHandlerRetentionConfig(PublisherConfig publisher, HandlerConfigData config,
      FileBasedEventHandlerConfiguration auditConfig) throws ConfigException
  {
    SortedSet<String> retentionPolicies = config.getRetentionPolicies();
    if (retentionPolicies.isEmpty())
@@ -650,7 +681,7 @@
   */
  public boolean isCommonAuditConfig(LogPublisherCfg config) throws ConfigException
  {
    return new PublisherConfig(serverContext, config).isCommonAudit();
    return new PublisherConfig(serverContext, config).isCommonAudit;
  }
  /**
@@ -705,42 +736,45 @@
  {
    private final LogPublisherCfg config;
    private final boolean isCommonAudit;
    private LogType logType;
    private LogType logType = LogType.UNCONFIGURED;
    private AuditType auditType;
    PublisherConfig(ServerContext serverContext, LogPublisherCfg config) throws ConfigException
    {
      this.config = config;
      Entry configEntry = DirectoryServer.getConfigEntry(config.dn());
      if (hasObjectClass(serverContext,configEntry, "ds-cfg-csv-file-access-log-publisher"))
      if (config instanceof JsonFileAccessLogPublisherCfg)
      {
        auditType = AuditType.JSON;
        logType = LogType.ACCESSLOG;
      }
      else if (config instanceof JsonFileHTTPAccessLogPublisherCfg)
      {
        auditType = AuditType.JSON;
        logType = LogType.HTTPLOG;
      }
      if (config instanceof CsvFileAccessLogPublisherCfg)
      {
        auditType = AuditType.CSV;
        logType = LogType.ACCESS;
        logType = LogType.ACCESSLOG;
      }
      else if (hasObjectClass(serverContext,configEntry, "ds-cfg-csv-file-http-access-log-publisher"))
      else if (config instanceof CsvFileHTTPAccessLogPublisherCfg)
      {
        auditType = AuditType.CSV;
        logType = LogType.HTTP_ACCESS;
        logType = LogType.HTTPLOG;
      }
      else if (hasObjectClass(serverContext,configEntry, "ds-cfg-external-access-log-publisher"))
      if (config instanceof ExternalAccessLogPublisherCfg)
      {
        auditType = AuditType.EXTERNAL;
        logType = LogType.ACCESS;
        logType = LogType.ACCESSLOG;
      }
      else if (hasObjectClass(serverContext,configEntry, "ds-cfg-external-http-access-log-publisher"))
      else if (config instanceof ExternalHTTPAccessLogPublisherCfg)
      {
        auditType = AuditType.EXTERNAL;
        logType = LogType.HTTP_ACCESS;
        logType = LogType.HTTPLOG;
      }
      isCommonAudit = auditType != null;
    }
    private boolean hasObjectClass(ServerContext serverContext, Entry entry, String objectClassName)
    {
      ObjectClass objectClass = serverContext.getSchema().getObjectClass(objectClassName);
      return !objectClass.isPlaceHolder() && entry.hasObjectClass(objectClass);
    }
    DN getDn()
    {
      return config.dn();
@@ -753,76 +787,22 @@
    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;
      return logType.getCommonAuditTopic(config);
    }
    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()));
      return logType.getCsvConfig(config);
    }
    JsonConfigData getJsonConfig() throws ConfigException
    {
      return logType.getJsonConfig(config);
    }
    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()));
      return logType.getExternalConfig(config);
    }
    @Override
@@ -851,25 +831,182 @@
  /** Types of audit handlers managed. */
  private enum AuditType
  {
    CSV, EXTERNAL
    CSV, JSON, EXTERNAL
  }
  /** Types of log managed. */
  /** Log types for LDAP or HTTP, to get specific configuration depending on the handler. **/
  private enum LogType
  {
    ACCESS, HTTP_ACCESS
    UNCONFIGURED
    {
      @Override
      String getCommonAuditTopic(LogPublisherCfg config) throws ConfigException
      {
        throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
      }
      @Override
      ExternalConfigData getExternalConfig(LogPublisherCfg config) throws ConfigException
      {
        throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
      }
      @Override
      CsvConfigData getCsvConfig(LogPublisherCfg config) throws ConfigException
      {
        throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
      }
      @Override
      JsonConfigData getJsonConfig(LogPublisherCfg config) throws ConfigException
      {
        throw new ConfigException(ERR_COMMON_AUDIT_UNSUPPORTED_LOG_PUBLISHER.get(config.dn()));
      }
      @Override
      boolean isHttp()
      {
        return false;
      }
    },
    HTTPLOG
    {
      @Override
      public String getCommonAuditTopic(LogPublisherCfg config)
      {
        return "http-access";
      }
      @Override
      public ExternalConfigData getExternalConfig(LogPublisherCfg config) throws ConfigException
      {
        ExternalHTTPAccessLogPublisherCfg conf = (ExternalHTTPAccessLogPublisherCfg) config;
        return new ExternalConfigData(conf.getConfigFile());
      }
      @Override
      public CsvConfigData getCsvConfig(LogPublisherCfg config) throws ConfigException
      {
        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());
      }
      @Override
      public JsonConfigData getJsonConfig(LogPublisherCfg config) throws ConfigException
      {
        JsonFileHTTPAccessLogPublisherCfg conf = (JsonFileHTTPAccessLogPublisherCfg) config;
        return new JsonConfigData(conf.getLogDirectory(), conf.getRotationPolicy(), conf.getRetentionPolicy());
      }
      @Override
      public boolean isHttp()
      {
        return true;
      }
    },
    ACCESSLOG
    {
      @Override
      public String getCommonAuditTopic(LogPublisherCfg config)
      {
        return "ldap-access";
      }
      @Override
      public ExternalConfigData getExternalConfig(LogPublisherCfg config) throws ConfigException
      {
        ExternalAccessLogPublisherCfg conf = (ExternalAccessLogPublisherCfg) config;
        return new ExternalConfigData(conf.getConfigFile());
      }
      @Override
      public CsvConfigData getCsvConfig(LogPublisherCfg config) throws ConfigException
      {
        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());
      }
      @Override
      public JsonConfigData getJsonConfig(LogPublisherCfg config) throws ConfigException
      {
        JsonFileAccessLogPublisherCfg conf = (JsonFileAccessLogPublisherCfg) config;
        return new JsonConfigData(conf.getLogDirectory(), conf.getRotationPolicy(), conf.getRetentionPolicy());
      }
      @Override
      public boolean isHttp()
      {
        return false;
      }
    };
    abstract String getCommonAuditTopic(LogPublisherCfg config) throws ConfigException;
    abstract ExternalConfigData getExternalConfig(LogPublisherCfg config) throws ConfigException;
    abstract CsvConfigData getCsvConfig(LogPublisherCfg config) throws ConfigException;
    abstract JsonConfigData getJsonConfig(LogPublisherCfg config) throws ConfigException;
    abstract boolean isHttp();
  }
  /**
   * Contains the parameters for a CSV handler.
   * Contains common parameters for non External CAUD handlers.
   * <p>
   * OpenDJ log publishers that logs to a CSV handler have the same parameters but do not share
   * OpenDJ log publishers that log to a CAUD 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.
   * is necessary to avoid duplicating code that setup configuration of the handler.
   */
  private static class CsvConfigData
  private abstract static class HandlerConfigData
  {
    private final String logDirectory;
    private final SortedSet<String> rotationPolicies;
    private final SortedSet<String> retentionPolicies;
    HandlerConfigData(String logDirectory, SortedSet<String> rotationPolicies, SortedSet<String> retentionPolicies)
    {
      this.logDirectory = logDirectory;
      this.rotationPolicies = rotationPolicies;
      this.retentionPolicies = retentionPolicies;
    }
    String getLogDirectory()
    {
      return logDirectory;
    }
    SortedSet<String> getRotationPolicies()
    {
      return rotationPolicies;
    }
    SortedSet<String> getRetentionPolicies()
    {
      return retentionPolicies;
    }
  }
  /**
   * Contains common parameters for the Json handler.
   */
  private static class JsonConfigData extends HandlerConfigData
  {
    JsonConfigData(String logDirectory, SortedSet<String> rotationPolicies, SortedSet<String> retentionPolicies)
    {
      super(logDirectory, rotationPolicies, retentionPolicies);
    }
  }
  /**
   * Contains common parameters for the CSV handler.
   * <p>
   * Adds CSV specific configuration to a CAUD handler.
   */
  private static class CsvConfigData extends HandlerConfigData
  {
    private final String eolSymbols;
    private final String delimiterChar;
    private final String quoteChar;
@@ -879,14 +1016,12 @@
    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;
      super(logDirectory, rotationPolicies, retentionPolicies);
      this.quoteChar = quoteChar;
      this.delimiterChar = delimiterChar;
      this.eolSymbols = eolSymbols;
@@ -896,8 +1031,6 @@
      this.signatureTimeInterval = signatureTimeInterval;
      this.keystoreFile = keystoreFile;
      this.keystorePinFile = keystorePinFile;
      this.rotationPolicies = rotationPolicies;
      this.retentionPolicies = retentionPolicies;
    }
    String getEndOfLineSymbols()
@@ -925,11 +1058,6 @@
      return filtered.charAt(0);
    }
    String getLogDirectory()
    {
      return logDirectory;
    }
    boolean isAsynchronous()
    {
      return asynchronous;
@@ -959,16 +1087,6 @@
    {
      return keystorePinFile;
    }
    SortedSet<String> getRotationPolicies()
    {
      return rotationPolicies;
    }
    SortedSet<String> getRetentionPolicies()
    {
      return retentionPolicies;
    }
  }
  /**
opendj-server-legacy/src/main/java/org/opends/server/loggers/JsonFileAccessLogPublisher.java
New file
@@ -0,0 +1,52 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.loggers;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.config.server.ConfigChangeResult;
import org.forgerock.opendj.config.server.ConfigurationChangeListener;
import org.forgerock.opendj.server.config.server.JsonFileAccessLogPublisherCfg;
import java.util.List;
/**
 * Common Audit publisher which publishes access events to Json files.
 */
final class JsonFileAccessLogPublisher
  extends CommonAuditAccessLogPublisher<JsonFileAccessLogPublisherCfg>
  implements ConfigurationChangeListener<JsonFileAccessLogPublisherCfg>
{
  @Override
  boolean shouldLogControlOids()
  {
    return getConfig().isLogControlOids();
  }
  @Override
  public ConfigChangeResult applyConfigurationChange(final JsonFileAccessLogPublisherCfg config)
  {
    setConfig(config);
    return new ConfigChangeResult();
  }
  @Override
  public boolean isConfigurationChangeAcceptable(final JsonFileAccessLogPublisherCfg config,
                                                 final List<LocalizableMessage> unacceptableReasons)
  {
    return true;
  }
}
opendj-server-legacy/src/messages/org/opends/messages/logger.properties
@@ -11,9 +11,7 @@
# information: "Portions Copyright [year] [name of copyright owner]".
#
# Copyright 2006-2008 Sun Microsystems, Inc.
# Portions Copyright 2015 ForgeRock AS.
# Portions Copyright 2015-2016 ForgeRock AS.
#
# Global directives
@@ -72,12 +70,11 @@
 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_FILE_BASED_HANDLER_CREATION_19=Error while creating common audit 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
 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
 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 \