| | |
| | | |
| | | |
| | | import static org.opends.messages.ConfigMessages.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | import static org.opends.server.util.StaticUtils.getFileForPath; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.MessageBuilder; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.std.meta.AccessLogFilteringCriteriaCfgDefn.*; |
| | | import org.opends.server.admin.std.meta.FileBasedAccessLogPublisherCfgDefn.*; |
| | | import org.opends.server.admin.std.server.AccessLogFilteringCriteriaCfg; |
| | | import org.opends.server.admin.std.server.AccessLogPublisherCfg; |
| | | import org.opends.server.admin.std.server.FileBasedAccessLogPublisherCfg; |
| | | import org.opends.server.api.AccessLogPublisher; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.ExtendedOperationHandler; |
| | | import org.opends.server.config.ConfigException; |
| | | 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.UnbindOperation; |
| | | import org.opends.server.core.*; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.TimeThread; |
| | | |
| | |
| | | { |
| | | |
| | | /** |
| | | * Criteria based filter. |
| | | */ |
| | | static final class CriteriaFilter implements Filter |
| | | { |
| | | private final AccessLogFilteringCriteriaCfg cfg; |
| | | private final boolean logConnectRecords; |
| | | private final boolean logDisconnectRecords; |
| | | private final EnumSet<OperationType> logOperationRecords; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new criteria based filter. |
| | | * |
| | | * @param cfg |
| | | * The access log filter criteria. |
| | | */ |
| | | CriteriaFilter(final AccessLogFilteringCriteriaCfg cfg) |
| | | { |
| | | this.cfg = cfg; |
| | | |
| | | // Pre-parse the log record types for more efficient queries. |
| | | if (cfg.getLogRecordType().isEmpty()) |
| | | { |
| | | logConnectRecords = true; |
| | | logDisconnectRecords = true; |
| | | |
| | | logOperationRecords = EnumSet.allOf(OperationType.class); |
| | | } |
| | | else |
| | | { |
| | | logConnectRecords = |
| | | cfg.getLogRecordType().contains(LogRecordType.CONNECT); |
| | | logDisconnectRecords = |
| | | cfg.getLogRecordType().contains(LogRecordType.DISCONNECT); |
| | | |
| | | logOperationRecords = EnumSet.noneOf(OperationType.class); |
| | | for (final LogRecordType type : cfg.getLogRecordType()) |
| | | { |
| | | switch (type) |
| | | { |
| | | case ABANDON: |
| | | logOperationRecords.add(OperationType.ABANDON); |
| | | break; |
| | | case ADD: |
| | | logOperationRecords.add(OperationType.ADD); |
| | | break; |
| | | case BIND: |
| | | logOperationRecords.add(OperationType.BIND); |
| | | break; |
| | | case COMPARE: |
| | | logOperationRecords.add(OperationType.COMPARE); |
| | | break; |
| | | case DELETE: |
| | | logOperationRecords.add(OperationType.DELETE); |
| | | break; |
| | | case EXTENDED: |
| | | logOperationRecords.add(OperationType.EXTENDED); |
| | | break; |
| | | case MODIFY: |
| | | logOperationRecords.add(OperationType.MODIFY); |
| | | break; |
| | | case RENAME: |
| | | logOperationRecords.add(OperationType.MODIFY_DN); |
| | | break; |
| | | case SEARCH: |
| | | logOperationRecords.add(OperationType.SEARCH); |
| | | break; |
| | | case UNBIND: |
| | | logOperationRecords.add(OperationType.UNBIND); |
| | | break; |
| | | default: // Ignore CONNECT/DISCONNECT |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConnectLoggable(final ClientConnection connection) |
| | | { |
| | | if (!logConnectRecords) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: other checks. |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isDisconnectLoggable(final ClientConnection connection) |
| | | { |
| | | if (!logDisconnectRecords) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: other checks. |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(final Operation operation) |
| | | { |
| | | if (!logOperationRecords.contains(operation.getOperationType())) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: other checks. |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isResponseLoggable(final Operation operation) |
| | | { |
| | | if (!logOperationRecords.contains(operation.getOperationType())) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: other checks. |
| | | |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Log message filter predicate. |
| | | */ |
| | | static interface Filter |
| | | { |
| | | /** |
| | | * Returns {@code true} if the provided client connect should be logged. |
| | | * |
| | | * @param connection |
| | | * The client connection. |
| | | * @return {@code true} if the provided client connect should be logged. |
| | | */ |
| | | boolean isConnectLoggable(ClientConnection connection); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if the provided client disconnect should be logged. |
| | | * |
| | | * @param connection |
| | | * The client connection. |
| | | * @return {@code true} if the provided client disconnect should be logged. |
| | | */ |
| | | boolean isDisconnectLoggable(ClientConnection connection); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if the provided request should be logged. |
| | | * |
| | | * @param operation |
| | |
| | | |
| | | |
| | | /** |
| | | * A filter which performs a logical AND over a set of sub-filters. |
| | | */ |
| | | static final class AndFilter implements Filter |
| | | { |
| | | private final Filter[] subFilters; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new AND filter. |
| | | * |
| | | * @param subFilters |
| | | * The sub-filters. |
| | | */ |
| | | AndFilter(Filter[] subFilters) |
| | | { |
| | | this.subFilters = subFilters; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(Operation operation) |
| | | { |
| | | for (Filter filter : subFilters) |
| | | { |
| | | if (!filter.isRequestLoggable(operation)) |
| | | { |
| | | // Fail fast. |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isResponseLoggable(Operation operation) |
| | | { |
| | | for (Filter filter : subFilters) |
| | | { |
| | | if (!filter.isResponseLoggable(operation)) |
| | | { |
| | | // Fail fast. |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A filter which performs a logical OR over a set of sub-filters. |
| | | */ |
| | | static final class OrFilter implements Filter |
| | |
| | | * @param subFilters |
| | | * The sub-filters. |
| | | */ |
| | | OrFilter(Filter[] subFilters) |
| | | OrFilter(final Filter[] subFilters) |
| | | { |
| | | this.subFilters = subFilters; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(Operation operation) |
| | | public boolean isConnectLoggable(final ClientConnection connection) |
| | | { |
| | | for (Filter filter : subFilters) |
| | | for (final Filter filter : subFilters) |
| | | { |
| | | if (filter.isConnectLoggable(connection)) |
| | | { |
| | | // Succeed fast. |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isDisconnectLoggable(final ClientConnection connection) |
| | | { |
| | | for (final Filter filter : subFilters) |
| | | { |
| | | if (filter.isDisconnectLoggable(connection)) |
| | | { |
| | | // Succeed fast. |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(final Operation operation) |
| | | { |
| | | for (final Filter filter : subFilters) |
| | | { |
| | | if (filter.isRequestLoggable(operation)) |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isResponseLoggable(Operation operation) |
| | | public boolean isResponseLoggable(final Operation operation) |
| | | { |
| | | for (Filter filter : subFilters) |
| | | for (final Filter filter : subFilters) |
| | | { |
| | | if (filter.isResponseLoggable(operation)) |
| | | { |
| | |
| | | * The root filter which first checks the logger configuration, delegating to |
| | | * a sub-filter if needed. |
| | | */ |
| | | final class RootFilter implements Filter |
| | | static final class RootFilter implements Filter |
| | | { |
| | | private final Filter subFilter; |
| | | private final boolean suppressInternalOperations; |
| | | private final boolean suppressSynchronizationOperations; |
| | | private final FilteringPolicy policy; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new root filter. |
| | | * |
| | | * @param suppressInternal |
| | | * Indicates whether internal operations should be suppressed. |
| | | * @param suppressSynchronization |
| | | * Indicates whether sync operations should be suppressed. |
| | | * @param policy |
| | | * The filtering policy. |
| | | * @param subFilter |
| | | * The sub-filter. |
| | | * The sub-filters. |
| | | */ |
| | | RootFilter(Filter subFilter) |
| | | RootFilter(final boolean suppressInternal, |
| | | final boolean suppressSynchronization, final FilteringPolicy policy, |
| | | final Filter subFilter) |
| | | { |
| | | this.suppressInternalOperations = suppressInternal; |
| | | this.suppressSynchronizationOperations = suppressSynchronization; |
| | | this.policy = policy; |
| | | this.subFilter = subFilter; |
| | | } |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(Operation operation) |
| | | public boolean isConnectLoggable(final ClientConnection connection) |
| | | { |
| | | if (isLoggable(operation)) |
| | | final long connectionID = connection.getConnectionID(); |
| | | if (connectionID >= 0 || !suppressInternalOperations) |
| | | { |
| | | // FIXME: actual behavior determined by default filter policy. |
| | | return subFilter.isRequestLoggable(operation); |
| | | switch (policy) |
| | | { |
| | | case INCLUSIVE: |
| | | return subFilter.isConnectLoggable(connection); |
| | | case EXCLUSIVE: |
| | | return !subFilter.isConnectLoggable(connection); |
| | | default: // NO_FILTERING: |
| | | return true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isResponseLoggable(Operation operation) |
| | | public boolean isDisconnectLoggable(final ClientConnection connection) |
| | | { |
| | | final long connectionID = connection.getConnectionID(); |
| | | if (connectionID >= 0 || !suppressInternalOperations) |
| | | { |
| | | switch (policy) |
| | | { |
| | | case INCLUSIVE: |
| | | return subFilter.isDisconnectLoggable(connection); |
| | | case EXCLUSIVE: |
| | | return !subFilter.isDisconnectLoggable(connection); |
| | | default: // NO_FILTERING: |
| | | return true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isRequestLoggable(final Operation operation) |
| | | { |
| | | if (isLoggable(operation)) |
| | | { |
| | | // FIXME: actual behavior determined by default filter policy. |
| | | return subFilter.isResponseLoggable(operation); |
| | | switch (policy) |
| | | { |
| | | case INCLUSIVE: |
| | | return subFilter.isRequestLoggable(operation); |
| | | case EXCLUSIVE: |
| | | return !subFilter.isRequestLoggable(operation); |
| | | default: // NO_FILTERING: |
| | | return true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isResponseLoggable(final Operation operation) |
| | | { |
| | | if (isLoggable(operation)) |
| | | { |
| | | switch (policy) |
| | | { |
| | | case INCLUSIVE: |
| | | return subFilter.isResponseLoggable(operation); |
| | | case EXCLUSIVE: |
| | | return !subFilter.isResponseLoggable(operation); |
| | | default: // NO_FILTERING: |
| | | return true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | |
| | | // Determines whether the provided operation should be logged. |
| | | private boolean isLoggable(Operation operation) |
| | | private boolean isLoggable(final Operation operation) |
| | | { |
| | | long connectionID = operation.getConnectionID(); |
| | | final long connectionID = operation.getConnectionID(); |
| | | if (connectionID < 0) |
| | | { |
| | | // This is an internal operation. |
| | |
| | | |
| | | |
| | | /** |
| | | * Filter criteria configuration listener. |
| | | */ |
| | | private final class FilterChangeListener implements |
| | | ConfigurationChangeListener<AccessLogFilteringCriteriaCfg>, |
| | | ConfigurationAddListener<AccessLogFilteringCriteriaCfg>, |
| | | ConfigurationDeleteListener<AccessLogFilteringCriteriaCfg> |
| | | { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd( |
| | | final AccessLogFilteringCriteriaCfg configuration) |
| | | { |
| | | // Rebuild the filter using the new configuration and criteria. |
| | | buildFilters(); |
| | | configuration.addChangeListener(this); |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | final AccessLogFilteringCriteriaCfg configuration) |
| | | { |
| | | // Rebuild the filter using the new configuration and criteria. |
| | | buildFilters(); |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | final AccessLogFilteringCriteriaCfg configuration) |
| | | { |
| | | // Rebuild the filter using the new configuration and criteria. |
| | | buildFilters(); |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationAddAcceptable( |
| | | final AccessLogFilteringCriteriaCfg configuration, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | final AccessLogFilteringCriteriaCfg configuration, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | final AccessLogFilteringCriteriaCfg configuration, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * The category to use when logging responses. |
| | | */ |
| | | private static final String CATEGORY_RESPONSE = "RES"; |
| | |
| | | * messages to standard out. |
| | | */ |
| | | public static TextAccessLogPublisher getStartupTextAccessPublisher( |
| | | TextWriter writer, boolean suppressInternal) |
| | | final TextWriter writer, final boolean suppressInternal) |
| | | { |
| | | TextAccessLogPublisher startupPublisher = new TextAccessLogPublisher(); |
| | | final TextAccessLogPublisher startupPublisher = |
| | | new TextAccessLogPublisher(); |
| | | startupPublisher.writer = writer; |
| | | startupPublisher.suppressInternalOperations = suppressInternal; |
| | | startupPublisher.setSubFilter(new AndFilter(new Filter[0])); // Always true. |
| | | startupPublisher.buildFilters(suppressInternal, false, |
| | | FilteringPolicy.NO_FILTERING); |
| | | return startupPublisher; |
| | | } |
| | | |
| | | |
| | | |
| | | private FileBasedAccessLogPublisherCfg currentConfig; |
| | | |
| | | private boolean suppressInternalOperations = true; |
| | | |
| | | private boolean suppressSynchronizationOperations = false; |
| | | |
| | | private TextWriter writer; |
| | | |
| | | private Filter filter; |
| | | private FileBasedAccessLogPublisherCfg currentConfig = null; |
| | | private TextWriter writer = null; |
| | | private Filter filter = null; |
| | | private FilterChangeListener filterChangeListener = null; |
| | | |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | FileBasedAccessLogPublisherCfg config) |
| | | final FileBasedAccessLogPublisherCfg config) |
| | | { |
| | | // Default result code. |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<Message> messages = new ArrayList<Message>(); |
| | | final ArrayList<Message> messages = new ArrayList<Message>(); |
| | | |
| | | suppressInternalOperations = config.isSuppressInternalOperations(); |
| | | suppressSynchronizationOperations = config |
| | | .isSuppressSynchronizationOperations(); |
| | | |
| | | File logFile = getFileForPath(config.getLogFile()); |
| | | FileNamingPolicy fnPolicy = new TimeStampNaming(logFile); |
| | | |
| | | final File logFile = getFileForPath(config.getLogFile()); |
| | | final FileNamingPolicy fnPolicy = new TimeStampNaming(logFile); |
| | | try |
| | | { |
| | | FilePermission perm = FilePermission.decodeUNIXMode(config |
| | | final FilePermission perm = FilePermission.decodeUNIXMode(config |
| | | .getLogFilePermissions()); |
| | | |
| | | boolean writerAutoFlush = config.isAutoFlush() |
| | | final boolean writerAutoFlush = config.isAutoFlush() |
| | | && !config.isAsynchronous(); |
| | | |
| | | TextWriter currentWriter; |
| | |
| | | |
| | | if (currentWriter instanceof MultifileTextWriter) |
| | | { |
| | | MultifileTextWriter mfWriter = (MultifileTextWriter) currentWriter; |
| | | final MultifileTextWriter mfWriter = |
| | | (MultifileTextWriter) currentWriter; |
| | | |
| | | mfWriter.setNamingPolicy(fnPolicy); |
| | | mfWriter.setFilePermissions(perm); |
| | |
| | | mfWriter.removeAllRetentionPolicies(); |
| | | mfWriter.removeAllRotationPolicies(); |
| | | |
| | | for (DN dn : config.getRotationPolicyDNs()) |
| | | for (final DN dn : config.getRotationPolicyDNs()) |
| | | { |
| | | mfWriter.addRotationPolicy(DirectoryServer.getRotationPolicy(dn)); |
| | | } |
| | | |
| | | for (DN dn : config.getRetentionPolicyDNs()) |
| | | for (final DN dn : config.getRetentionPolicyDNs()) |
| | | { |
| | | mfWriter.addRetentionPolicy(DirectoryServer.getRetentionPolicy(dn)); |
| | | } |
| | |
| | | if (writer instanceof AsyncronousTextWriter && !config.isAsynchronous()) |
| | | { |
| | | // The asynchronous setting is being turned off. |
| | | AsyncronousTextWriter asyncWriter = ((AsyncronousTextWriter) writer); |
| | | final AsyncronousTextWriter asyncWriter = |
| | | ((AsyncronousTextWriter) writer); |
| | | writer = mfWriter; |
| | | asyncWriter.shutdown(false); |
| | | } |
| | |
| | | if (writer instanceof ParallelTextWriter && !config.isAsynchronous()) |
| | | { |
| | | // The asynchronous setting is being turned off. |
| | | ParallelTextWriter asyncWriter = ((ParallelTextWriter) writer); |
| | | final ParallelTextWriter asyncWriter = ((ParallelTextWriter) writer); |
| | | writer = mfWriter; |
| | | asyncWriter.shutdown(false); |
| | | } |
| | |
| | | && config.isAsynchronous()) |
| | | { |
| | | // The asynchronous setting is being turned on. |
| | | AsyncronousTextWriter asyncWriter = new AsyncronousTextWriter( |
| | | final AsyncronousTextWriter asyncWriter = new AsyncronousTextWriter( |
| | | "Asyncronous Text Writer for " + config.dn().toNormalizedString(), |
| | | config.getQueueSize(), config.isAutoFlush(), mfWriter); |
| | | writer = asyncWriter; |
| | |
| | | if (!(writer instanceof ParallelTextWriter) && config.isAsynchronous()) |
| | | { |
| | | // The asynchronous setting is being turned on. |
| | | ParallelTextWriter asyncWriter = new ParallelTextWriter( |
| | | final ParallelTextWriter asyncWriter = new ParallelTextWriter( |
| | | "Parallel Text Writer for " + config.dn().toNormalizedString(), |
| | | config.isAutoFlush(), mfWriter); |
| | | writer = asyncWriter; |
| | |
| | | adminActionRequired = true; |
| | | } |
| | | |
| | | // FIXME: use a dummy set of sub-filters for now. |
| | | setSubFilter(new AndFilter(new Filter[0])); // Always true. |
| | | |
| | | currentConfig = config; |
| | | |
| | | // Rebuild the filter using the new configuration and criteria. |
| | | buildFilters(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | catch (final Exception e) |
| | | { |
| | | Message message = ERR_CONFIG_LOGGING_CANNOT_CREATE_WRITER.get(config.dn() |
| | | .toString(), stackTraceToSingleLineString(e)); |
| | | final Message message = ERR_CONFIG_LOGGING_CANNOT_CREATE_WRITER.get( |
| | | config.dn().toString(), stackTraceToSingleLineString(e)); |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | messages.add(message); |
| | | |
| | |
| | | if (currentConfig != null) |
| | | { |
| | | currentConfig.removeFileBasedAccessChangeListener(this); |
| | | |
| | | for (final String criteriaName : currentConfig |
| | | .listAccessLogFilteringCriteria()) |
| | | { |
| | | try |
| | | { |
| | | currentConfig.getAccessLogFilteringCriteria(criteriaName) |
| | | .removeChangeListener(filterChangeListener); |
| | | } |
| | | catch (final ConfigException e) |
| | | { |
| | | // Ignore. |
| | | } |
| | | } |
| | | currentConfig |
| | | .removeAccessLogFilteringCriteriaAddListener(filterChangeListener); |
| | | currentConfig |
| | | .removeAccessLogFilteringCriteriaDeleteListener(filterChangeListener); |
| | | } |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void initializeAccessLogPublisher(FileBasedAccessLogPublisherCfg cfg) |
| | | throws ConfigException, InitializationException |
| | | public void initializeAccessLogPublisher( |
| | | final FileBasedAccessLogPublisherCfg cfg) throws ConfigException, |
| | | InitializationException |
| | | { |
| | | File logFile = getFileForPath(cfg.getLogFile()); |
| | | FileNamingPolicy fnPolicy = new TimeStampNaming(logFile); |
| | | final File logFile = getFileForPath(cfg.getLogFile()); |
| | | final FileNamingPolicy fnPolicy = new TimeStampNaming(logFile); |
| | | |
| | | try |
| | | { |
| | | FilePermission perm = FilePermission.decodeUNIXMode(cfg |
| | | final FilePermission perm = FilePermission.decodeUNIXMode(cfg |
| | | .getLogFilePermissions()); |
| | | |
| | | LogPublisherErrorHandler errorHandler = new LogPublisherErrorHandler( |
| | | cfg.dn()); |
| | | final LogPublisherErrorHandler errorHandler = |
| | | new LogPublisherErrorHandler(cfg.dn()); |
| | | |
| | | boolean writerAutoFlush = cfg.isAutoFlush() |
| | | final boolean writerAutoFlush = cfg.isAutoFlush() |
| | | && !cfg.isAsynchronous(); |
| | | |
| | | MultifileTextWriter writer = new MultifileTextWriter( |
| | | final MultifileTextWriter writer = new MultifileTextWriter( |
| | | "Multifile Text Writer for " + cfg.dn().toNormalizedString(), |
| | | cfg.getTimeInterval(), fnPolicy, perm, errorHandler, "UTF-8", |
| | | writerAutoFlush, cfg.isAppend(), (int) cfg.getBufferSize()); |
| | | |
| | | // Validate retention and rotation policies. |
| | | for (DN dn : cfg.getRotationPolicyDNs()) |
| | | for (final DN dn : cfg.getRotationPolicyDNs()) |
| | | { |
| | | writer.addRotationPolicy(DirectoryServer.getRotationPolicy(dn)); |
| | | } |
| | | |
| | | for (DN dn : cfg.getRetentionPolicyDNs()) |
| | | for (final DN dn : cfg.getRetentionPolicyDNs()) |
| | | { |
| | | writer.addRetentionPolicy(DirectoryServer.getRetentionPolicy(dn)); |
| | | } |
| | |
| | | this.writer = writer; |
| | | } |
| | | } |
| | | catch (DirectoryException e) |
| | | catch (final DirectoryException e) |
| | | { |
| | | Message message = ERR_CONFIG_LOGGING_CANNOT_CREATE_WRITER.get(cfg.dn() |
| | | .toString(), String.valueOf(e)); |
| | | final Message message = ERR_CONFIG_LOGGING_CANNOT_CREATE_WRITER.get(cfg |
| | | .dn().toString(), String.valueOf(e)); |
| | | throw new InitializationException(message, e); |
| | | |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | Message message = ERR_CONFIG_LOGGING_CANNOT_OPEN_FILE.get( |
| | | final Message message = ERR_CONFIG_LOGGING_CANNOT_OPEN_FILE.get( |
| | | logFile.toString(), cfg.dn().toString(), String.valueOf(e)); |
| | | throw new InitializationException(message, e); |
| | | |
| | | } |
| | | |
| | | suppressInternalOperations = cfg.isSuppressInternalOperations(); |
| | | suppressSynchronizationOperations = cfg |
| | | .isSuppressSynchronizationOperations(); |
| | | currentConfig = cfg; |
| | | |
| | | // FIXME: use a dummy set of sub-filters for now. |
| | | setSubFilter(new AndFilter(new Filter[0])); // Always true. |
| | | // Rebuild the filter using the new configuration and criteria. |
| | | buildFilters(); |
| | | |
| | | cfg.addFileBasedAccessChangeListener(this); |
| | | // Add change listeners. |
| | | filterChangeListener = new FilterChangeListener(); |
| | | for (final String criteriaName : currentConfig |
| | | .listAccessLogFilteringCriteria()) |
| | | { |
| | | try |
| | | { |
| | | currentConfig.getAccessLogFilteringCriteria(criteriaName) |
| | | .addChangeListener(filterChangeListener); |
| | | } |
| | | catch (final ConfigException e) |
| | | { |
| | | // Ignore. |
| | | } |
| | | } |
| | | currentConfig |
| | | .addAccessLogFilteringCriteriaAddListener(filterChangeListener); |
| | | currentConfig |
| | | .addAccessLogFilteringCriteriaDeleteListener(filterChangeListener); |
| | | |
| | | currentConfig.addFileBasedAccessChangeListener(this); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isConfigurationAcceptable(AccessLogPublisherCfg configuration, |
| | | List<Message> unacceptableReasons) |
| | | public boolean isConfigurationAcceptable( |
| | | final AccessLogPublisherCfg configuration, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | FileBasedAccessLogPublisherCfg config = |
| | | final FileBasedAccessLogPublisherCfg config = |
| | | (FileBasedAccessLogPublisherCfg) configuration; |
| | | return isConfigurationChangeAcceptable(config, unacceptableReasons); |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | FileBasedAccessLogPublisherCfg config, List<Message> unacceptableReasons) |
| | | final FileBasedAccessLogPublisherCfg config, |
| | | final List<Message> unacceptableReasons) |
| | | { |
| | | // Make sure the permission is valid. |
| | | try |
| | | { |
| | | FilePermission filePerm = FilePermission.decodeUNIXMode(config |
| | | final FilePermission filePerm = FilePermission.decodeUNIXMode(config |
| | | .getLogFilePermissions()); |
| | | if (!filePerm.isOwnerWritable()) |
| | | { |
| | | Message message = ERR_CONFIG_LOGGING_INSANE_MODE.get(config |
| | | final Message message = ERR_CONFIG_LOGGING_INSANE_MODE.get(config |
| | | .getLogFilePermissions()); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | } |
| | | catch (DirectoryException e) |
| | | catch (final DirectoryException e) |
| | | { |
| | | Message message = ERR_CONFIG_LOGGING_MODE_INVALID.get( |
| | | final Message message = ERR_CONFIG_LOGGING_MODE_INVALID.get( |
| | | config.getLogFilePermissions(), String.valueOf(e)); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | |
| | | * abandon request. |
| | | */ |
| | | @Override |
| | | public void logAbandonRequest(AbandonOperation abandonOperation) |
| | | public void logAbandonRequest(final AbandonOperation abandonOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(abandonOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(abandonOperation, "ABANDON", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" idToAbandon="); |
| | | buffer.append(abandonOperation.getIDToAbandon()); |
| | | if (abandonOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * abandon request. |
| | | */ |
| | | @Override |
| | | public void logAbandonResult(AbandonOperation abandonOperation) |
| | | public void logAbandonResult(final AbandonOperation abandonOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(abandonOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(abandonOperation, "ABANDON", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(abandonOperation.getResultCode().getIntValue()); |
| | | MessageBuilder msg = abandonOperation.getErrorMessage(); |
| | | final MessageBuilder msg = abandonOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | * request. |
| | | */ |
| | | @Override |
| | | public void logAddRequest(AddOperation addOperation) |
| | | public void logAddRequest(final AddOperation addOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(addOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(addOperation, "ADD", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" dn=\""); |
| | | buffer.append(addOperation.getRawEntryDN().toString()); |
| | | buffer.append("\""); |
| | | if (addOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * response. |
| | | */ |
| | | @Override |
| | | public void logAddResponse(AddOperation addOperation) |
| | | public void logAddResponse(final AddOperation addOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(addOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(addOperation, "ADD", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(addOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = addOperation.getErrorMessage(); |
| | | final MessageBuilder msg = addOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(addOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = addOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = addOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * request. |
| | | */ |
| | | @Override |
| | | public void logBindRequest(BindOperation bindOperation) |
| | | public void logBindRequest(final BindOperation bindOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(bindOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(bindOperation, "BIND", CATEGORY_REQUEST, buffer); |
| | | |
| | | final String protocolVersion = bindOperation.getProtocolVersion(); |
| | |
| | | buffer.append(bindOperation.getRawBindDN().toString()); |
| | | buffer.append("\""); |
| | | if (bindOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * bind response. |
| | | */ |
| | | @Override |
| | | public void logBindResponse(BindOperation bindOperation) |
| | | public void logBindResponse(final BindOperation bindOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(bindOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(bindOperation, "BIND", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(bindOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = bindOperation.getErrorMessage(); |
| | | final MessageBuilder msg = bindOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | buffer.append('\"'); |
| | | } |
| | | |
| | | Message failureMessage = bindOperation.getAuthFailureReason(); |
| | | final Message failureMessage = bindOperation.getAuthFailureReason(); |
| | | if (failureMessage != null) |
| | | { |
| | | buffer.append(" authFailureID="); |
| | |
| | | |
| | | if (bindOperation.getResultCode() == ResultCode.SUCCESS) |
| | | { |
| | | AuthenticationInfo authInfo = bindOperation.getAuthenticationInfo(); |
| | | final AuthenticationInfo authInfo = bindOperation.getAuthenticationInfo(); |
| | | if (authInfo != null) |
| | | { |
| | | DN authDN = authInfo.getAuthenticationDN(); |
| | | final DN authDN = authInfo.getAuthenticationDN(); |
| | | if (authDN != null) |
| | | { |
| | | buffer.append(" authDN=\""); |
| | | authDN.toString(buffer); |
| | | buffer.append('\"'); |
| | | |
| | | DN authzDN = authInfo.getAuthorizationDN(); |
| | | final DN authzDN = authInfo.getAuthorizationDN(); |
| | | if (!authDN.equals(authzDN)) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * compare request. |
| | | */ |
| | | @Override |
| | | public void logCompareRequest(CompareOperation compareOperation) |
| | | public void logCompareRequest(final CompareOperation compareOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(compareOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(compareOperation, "COMPARE", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" dn=\""); |
| | | buffer.append(compareOperation.getRawEntryDN().toString()); |
| | | buffer.append("\" attr="); |
| | | buffer.append(compareOperation.getAttributeType().getNameOrOID()); |
| | | if (compareOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * compare response. |
| | | */ |
| | | @Override |
| | | public void logCompareResponse(CompareOperation compareOperation) |
| | | public void logCompareResponse(final CompareOperation compareOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(compareOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(compareOperation, "COMPARE", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(compareOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = compareOperation.getErrorMessage(); |
| | | final MessageBuilder msg = compareOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(compareOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = compareOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = compareOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * The client connection that has been established. |
| | | */ |
| | | @Override |
| | | public void logConnect(ClientConnection clientConnection) |
| | | public void logConnect(final ClientConnection clientConnection) |
| | | { |
| | | // FIXME: implement filtering. |
| | | long connectionID = clientConnection.getConnectionID(); |
| | | |
| | | if (connectionID < 0 && suppressInternalOperations) |
| | | if (!filter.isConnectLoggable(clientConnection)) |
| | | { |
| | | return; |
| | | } |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | |
| | | final long connectionID = clientConnection.getConnectionID(); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | buffer.append("["); |
| | | buffer.append(TimeThread.getLocalTime()); |
| | | buffer.append("]"); |
| | |
| | | * request. |
| | | */ |
| | | @Override |
| | | public void logDeleteRequest(DeleteOperation deleteOperation) |
| | | public void logDeleteRequest(final DeleteOperation deleteOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(deleteOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(deleteOperation, "DELETE", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" dn=\""); |
| | | buffer.append(deleteOperation.getRawEntryDN().toString()); |
| | | buffer.append("\""); |
| | | if (deleteOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * delete response. |
| | | */ |
| | | @Override |
| | | public void logDeleteResponse(DeleteOperation deleteOperation) |
| | | public void logDeleteResponse(final DeleteOperation deleteOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(deleteOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(deleteOperation, "DELETE", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(deleteOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = deleteOperation.getErrorMessage(); |
| | | final MessageBuilder msg = deleteOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(deleteOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = deleteOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = deleteOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * about the disconnect. |
| | | */ |
| | | @Override |
| | | public void logDisconnect(ClientConnection clientConnection, |
| | | DisconnectReason disconnectReason, Message message) |
| | | public void logDisconnect(final ClientConnection clientConnection, |
| | | final DisconnectReason disconnectReason, final Message message) |
| | | { |
| | | // FIXME: implement filtering. |
| | | long connectionID = clientConnection.getConnectionID(); |
| | | if (connectionID < 0 && suppressInternalOperations) |
| | | if (!filter.isDisconnectLoggable(clientConnection)) |
| | | { |
| | | return; |
| | | } |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | |
| | | final long connectionID = clientConnection.getConnectionID(); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | buffer.append("["); |
| | | buffer.append(TimeThread.getLocalTime()); |
| | | buffer.append("]"); |
| | |
| | | * the extended request. |
| | | */ |
| | | @Override |
| | | public void logExtendedRequest(ExtendedOperation extendedOperation) |
| | | public void logExtendedRequest(final ExtendedOperation extendedOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(extendedOperation)) |
| | | { |
| | |
| | | } |
| | | |
| | | String name = null; |
| | | String oid = extendedOperation.getRequestOID(); |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final String oid = extendedOperation.getRequestOID(); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(extendedOperation, "EXTENDED", CATEGORY_REQUEST, buffer); |
| | | ExtendedOperationHandler<?> extOpHandler = DirectoryServer |
| | | final ExtendedOperationHandler<?> extOpHandler = DirectoryServer |
| | | .getExtendedOperationHandler(oid); |
| | | if (extOpHandler != null) |
| | | { |
| | |
| | | * extended response. |
| | | */ |
| | | @Override |
| | | public void logExtendedResponse(ExtendedOperation extendedOperation) |
| | | public void logExtendedResponse(final ExtendedOperation extendedOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(extendedOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(extendedOperation, "EXTENDED", CATEGORY_RESPONSE, buffer); |
| | | |
| | | String name = null; |
| | | String oid = extendedOperation.getResponseOID(); |
| | | final String oid = extendedOperation.getResponseOID(); |
| | | if (oid != null) |
| | | { |
| | | ExtendedOperationHandler<?> extOpHandler = DirectoryServer |
| | | final ExtendedOperationHandler<?> extOpHandler = DirectoryServer |
| | | .getExtendedOperationHandler(oid); |
| | | if (extOpHandler != null) |
| | | { |
| | |
| | | buffer.append(" result="); |
| | | buffer.append(extendedOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = extendedOperation.getErrorMessage(); |
| | | final MessageBuilder msg = extendedOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | * modify DN request. |
| | | */ |
| | | @Override |
| | | public void logModifyDNRequest(ModifyDNOperation modifyDNOperation) |
| | | public void logModifyDNRequest(final ModifyDNOperation modifyDNOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(modifyDNOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(modifyDNOperation, "MODIFYDN", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" dn=\""); |
| | | buffer.append(modifyDNOperation.getRawEntryDN().toString()); |
| | |
| | | buffer.append("\" deleteOldRDN="); |
| | | buffer.append(modifyDNOperation.deleteOldRDN()); |
| | | |
| | | ByteString newSuperior = modifyDNOperation.getRawNewSuperior(); |
| | | final ByteString newSuperior = modifyDNOperation.getRawNewSuperior(); |
| | | if (newSuperior != null) |
| | | { |
| | | buffer.append(" newSuperior=\""); |
| | | buffer.append(newSuperior.toString()); |
| | | } |
| | | if (modifyDNOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * the modify DN response. |
| | | */ |
| | | @Override |
| | | public void logModifyDNResponse(ModifyDNOperation modifyDNOperation) |
| | | public void logModifyDNResponse(final ModifyDNOperation modifyDNOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(modifyDNOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(modifyDNOperation, "MODIFYDN", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(modifyDNOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = modifyDNOperation.getErrorMessage(); |
| | | final MessageBuilder msg = modifyDNOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(modifyDNOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = modifyDNOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = modifyDNOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * modify request. |
| | | */ |
| | | @Override |
| | | public void logModifyRequest(ModifyOperation modifyOperation) |
| | | public void logModifyRequest(final ModifyOperation modifyOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(modifyOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(modifyOperation, "MODIFY", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" dn=\""); |
| | | buffer.append(modifyOperation.getRawEntryDN().toString()); |
| | | buffer.append("\""); |
| | | if (modifyOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * modify response. |
| | | */ |
| | | @Override |
| | | public void logModifyResponse(ModifyOperation modifyOperation) |
| | | public void logModifyResponse(final ModifyOperation modifyOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(modifyOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(modifyOperation, "MODIFY", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(modifyOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = modifyOperation.getErrorMessage(); |
| | | final MessageBuilder msg = modifyOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(modifyOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = modifyOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = modifyOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * request. |
| | | */ |
| | | @Override |
| | | public void logSearchRequest(SearchOperation searchOperation) |
| | | public void logSearchRequest(final SearchOperation searchOperation) |
| | | { |
| | | if (!filter.isRequestLoggable(searchOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(192); |
| | | final StringBuilder buffer = new StringBuilder(192); |
| | | appendHeader(searchOperation, "SEARCH", CATEGORY_REQUEST, buffer); |
| | | buffer.append(" base=\""); |
| | | buffer.append(searchOperation.getRawBaseDN().toString()); |
| | |
| | | buffer.append(" filter=\""); |
| | | searchOperation.getRawFilter().toString(buffer); |
| | | |
| | | LinkedHashSet<String> attrs = searchOperation.getAttributes(); |
| | | final LinkedHashSet<String> attrs = searchOperation.getAttributes(); |
| | | if ((attrs == null) || attrs.isEmpty()) |
| | | { |
| | | buffer.append("\" attrs=\"ALL\""); |
| | |
| | | { |
| | | buffer.append("\" attrs=\""); |
| | | |
| | | Iterator<String> iterator = attrs.iterator(); |
| | | final Iterator<String> iterator = attrs.iterator(); |
| | | buffer.append(iterator.next()); |
| | | while (iterator.hasNext()) |
| | | { |
| | |
| | | buffer.append("\""); |
| | | } |
| | | if (searchOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | * search result done message. |
| | | */ |
| | | @Override |
| | | public void logSearchResultDone(SearchOperation searchOperation) |
| | | public void logSearchResultDone(final SearchOperation searchOperation) |
| | | { |
| | | if (!filter.isResponseLoggable(searchOperation)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(128); |
| | | final StringBuilder buffer = new StringBuilder(128); |
| | | appendHeader(searchOperation, "SEARCH", CATEGORY_RESPONSE, buffer); |
| | | buffer.append(" result="); |
| | | buffer.append(searchOperation.getResultCode().getIntValue()); |
| | | |
| | | MessageBuilder msg = searchOperation.getErrorMessage(); |
| | | final MessageBuilder msg = searchOperation.getErrorMessage(); |
| | | if ((msg != null) && (msg.length() > 0)) |
| | | { |
| | | buffer.append(" message=\""); |
| | |
| | | |
| | | logAdditionalLogItems(searchOperation, buffer); |
| | | |
| | | DN proxiedAuthDN = searchOperation.getProxiedAuthorizationDN(); |
| | | final DN proxiedAuthDN = searchOperation.getProxiedAuthorizationDN(); |
| | | if (proxiedAuthDN != null) |
| | | { |
| | | buffer.append(" authzDN=\""); |
| | |
| | | * request. |
| | | */ |
| | | @Override |
| | | public void logUnbind(UnbindOperation unbindOperation) |
| | | public void logUnbind(final UnbindOperation unbindOperation) |
| | | { |
| | | // FIXME: ensure that these are logged in combined mode. |
| | | if (!filter.isRequestLoggable(unbindOperation)) |
| | |
| | | return; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(100); |
| | | final StringBuilder buffer = new StringBuilder(100); |
| | | appendHeader(unbindOperation, "UNBIND", CATEGORY_REQUEST, buffer); |
| | | if (unbindOperation.isSynchronizationOperation()) |
| | | { |
| | | buffer.append(" type=synchronization"); |
| | | } |
| | | |
| | | writer.writeRecord(buffer.toString()); |
| | | } |
| | |
| | | |
| | | |
| | | // Appends the common log header information to the provided buffer. |
| | | private void appendHeader(Operation operation, String opType, |
| | | String category, StringBuilder buffer) |
| | | private void appendHeader(final Operation operation, final String opType, |
| | | final String category, final StringBuilder buffer) |
| | | { |
| | | buffer.append('['); |
| | | buffer.append(TimeThread.getLocalTime()); |
| | |
| | | |
| | | |
| | | |
| | | // Appends additional log items to the provided builder. |
| | | private void logAdditionalLogItems(Operation operation, StringBuilder builder) |
| | | // Build an appropriate set of filters based on the configuration. |
| | | private void buildFilters() |
| | | { |
| | | for (AdditionalLogItem item : operation.getAdditionalLogItems()) |
| | | buildFilters(currentConfig.isSuppressInternalOperations(), |
| | | currentConfig.isSuppressSynchronizationOperations(), |
| | | currentConfig.getFilteringPolicy()); |
| | | } |
| | | |
| | | |
| | | |
| | | private void buildFilters(final boolean suppressInternal, |
| | | final boolean suppressSynchronization, final FilteringPolicy policy) |
| | | { |
| | | final ArrayList<Filter> subFilters = new ArrayList<Filter>(); |
| | | if (currentConfig != null) |
| | | { |
| | | for (final String criteriaName : currentConfig |
| | | .listAccessLogFilteringCriteria()) |
| | | { |
| | | try |
| | | { |
| | | final AccessLogFilteringCriteriaCfg cfg = currentConfig |
| | | .getAccessLogFilteringCriteria(criteriaName); |
| | | subFilters.add(new CriteriaFilter(cfg)); |
| | | } |
| | | catch (final ConfigException e) |
| | | { |
| | | // TODO: Unable to decode this access log criteria, so log a warning |
| | | // and continue. |
| | | } |
| | | } |
| | | } |
| | | final Filter orFilter = new OrFilter(subFilters.toArray(new Filter[0])); |
| | | filter = new RootFilter(suppressInternal, suppressSynchronization, policy, |
| | | orFilter); |
| | | } |
| | | |
| | | |
| | | |
| | | // Appends additional log items to the provided builder. |
| | | private void logAdditionalLogItems(final Operation operation, |
| | | final StringBuilder builder) |
| | | { |
| | | for (final AdditionalLogItem item : operation.getAdditionalLogItems()) |
| | | { |
| | | builder.append(' '); |
| | | item.toString(builder); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // Sets the sub-filter. |
| | | private void setSubFilter(Filter subFilter) |
| | | { |
| | | this.filter = new RootFilter(subFilter); |
| | | } |
| | | } |