001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Copyright 2016-2021 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.common.api;
028
029
030
031import java.io.File;
032import java.util.Collections;
033import java.util.List;
034import java.util.Map;
035
036import com.unboundid.directory.sdk.broker.internal.BrokerExtension;
037import com.unboundid.directory.sdk.common.config.LogFileRotationListenerConfig;
038import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
039import com.unboundid.directory.sdk.common.internal.Reconfigurable;
040import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
041import com.unboundid.directory.sdk.common.types.ServerContext;
042import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
043import com.unboundid.directory.sdk.metrics.internal.MetricsEngineExtension;
044import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
045import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
046import com.unboundid.ldap.sdk.LDAPException;
047import com.unboundid.ldap.sdk.ResultCode;
048import com.unboundid.util.Extensible;
049import com.unboundid.util.ThreadSafety;
050import com.unboundid.util.ThreadSafetyLevel;
051import com.unboundid.util.args.ArgumentException;
052import com.unboundid.util.args.ArgumentParser;
053
054
055
056/**
057 * This class defines an API that may be used to perform custom processing
058 * whenever a log file is rotated.
059 * <BR>
060 * <H2>Configuring Log File Rotation Listeners</H2>
061 * In order to configure a log file rotation listener created using this API,
062 * use a command like:
063 * <PRE>
064 *      dsconfig create-log-file-rotation-listener \
065 *           --listener-name "<I>{listener-name}</I>" \
066 *           --type third-party \
067 *           --set enabled:true \
068 *           --set "extension-class:<I>{class-name}</I>" \
069 *           --set "extension-argument:<I>{name=value}</I>"
070 * </PRE>
071 * where "<I>{listener-name}</I>" is the name to use for the log file rotation
072 * listener instance, "<I>{class-name}</I>" is the fully-qualified name of the
073 * Java class that extends
074 * {@code com.unboundid.directory.sdk.common.api.LogFileRotationListener},
075 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
076 * provide to the listener.  If multiple arguments should be provided to the
077 * listener, then the
078 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
079 * provided multiple times.
080 */
081@Extensible()
082@DirectoryServerExtension()
083@DirectoryProxyServerExtension(appliesToLocalContent=true,
084     appliesToRemoteContent=true)
085@SynchronizationServerExtension(appliesToLocalContent=true,
086     appliesToSynchronizedContent=false)
087@MetricsEngineExtension()
088@BrokerExtension()
089@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
090public abstract class LogFileRotationListener
091       implements UnboundIDExtension,
092                  Reconfigurable<LogFileRotationListenerConfig>,
093                  ExampleUsageProvider
094{
095  /**
096   * Creates a new instance of this log file rotation listener.  All log file
097   * rotation listener implementations must include a default constructor, but
098   * any initialization should generally be done in the
099   * {@code initializeLogFileRotationListener} method.
100   */
101  public LogFileRotationListener()
102  {
103    // No implementation is required.
104  }
105
106
107
108  /**
109   * {@inheritDoc}
110   */
111  public abstract String getExtensionName();
112
113
114
115  /**
116   * {@inheritDoc}
117   */
118  public abstract String[] getExtensionDescription();
119
120
121
122  /**
123   * {@inheritDoc}
124   */
125  public void defineConfigArguments(final ArgumentParser parser)
126         throws ArgumentException
127  {
128    // No arguments will be allowed by default.
129  }
130
131
132
133  /**
134   * Initializes this log file rotation listener.
135   *
136   * @param  serverContext  A handle to the server context for the server in
137   *                        which this extension is running.
138   * @param  config         The general configuration for this log file rotation
139   *                        listener.
140   * @param  parser         The argument parser which has been initialized from
141   *                        the configuration for this log file rotation
142   *                        listener.
143   *
144   * @throws  LDAPException  If a problem occurs while initializing this log
145   *                         file rotation listener.
146   */
147  public void initializeLogFileRotationListener(
148                   final ServerContext serverContext,
149                   final LogFileRotationListenerConfig config,
150                   final ArgumentParser parser)
151         throws LDAPException
152  {
153    // No initialization will be performed by default.
154  }
155
156
157
158  /**
159   * {@inheritDoc}
160   */
161  public boolean isConfigurationAcceptable(
162                      final LogFileRotationListenerConfig config,
163                      final ArgumentParser parser,
164                      final List<String> unacceptableReasons)
165  {
166    // No extended validation will be performed by default.
167    return true;
168  }
169
170
171
172  /**
173   * {@inheritDoc}
174   */
175  public ResultCode applyConfiguration(
176                         final LogFileRotationListenerConfig config,
177                         final ArgumentParser parser,
178                         final List<String> adminActionsRequired,
179                         final List<String> messages)
180  {
181    // By default, no configuration changes will be applied.  If there are any
182    // arguments, then add an admin action message indicating that the extension
183    // needs to be restarted for any changes to take effect.
184    if (! parser.getNamedArguments().isEmpty())
185    {
186      adminActionsRequired.add(
187           "No configuration change has actually been applied.  The new " +
188                "configuration will not take effect until this log file " +
189                "rotation listener is disabled and re-enabled or until the " +
190                "server is restarted.");
191    }
192
193    return ResultCode.SUCCESS;
194  }
195
196
197
198  /**
199   * Performs any cleanup which may be necessary when this log file rotation
200   * listener is to be taken out of service.
201   */
202  public void finalizeLogFileRotationListener()
203  {
204    // No implementation is required.
205  }
206
207
208
209  /**
210   * Performs any appropriate processing for a log file that has been rotated.
211   *
212   * @param  f  The log file that has been rotated.  This file must not be
213   *            deleted, moved, renamed, or otherwise altered during processing.
214   *
215   * @throws  LDAPException  If a problem is encountered during processing.
216   */
217  public abstract void doPostRotationProcessing(final File f)
218         throws LDAPException;
219
220
221
222  /**
223   * {@inheritDoc}
224   */
225  public Map<List<String>,String> getExamplesArgumentSets()
226  {
227    return Collections.emptyMap();
228  }
229}