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 *      Portions Copyright 2018-2023 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.ds.api;
028
029
030
031import java.time.ZonedDateTime;
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.internal.ExampleUsageProvider;
038import com.unboundid.directory.sdk.common.internal.Reconfigurable;
039import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
040import com.unboundid.directory.sdk.ds.config.RecurringTaskConfig;
041import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
042import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
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.ReadOnlyEntry;
048import com.unboundid.ldap.sdk.ResultCode;
049import com.unboundid.util.Extensible;
050import com.unboundid.util.ThreadSafety;
051import com.unboundid.util.ThreadSafetyLevel;
052import com.unboundid.util.args.ArgumentException;
053import com.unboundid.util.args.ArgumentParser;
054
055
056
057/**
058 * This class defines an API that must be implemented by extensions that may be
059 * used to schedule administrative tasks on a recurring basis.  Recurring
060 * tasks are part of a recurring task chain, which combines the configuration
061 * needed to define the schedule with the recurring tasks that define the
062 * content of the tasks to schedule.
063 * <BR><BR>
064 * Recurring tasks created via this API can only be used to schedule
065 * {@link Task} instances that have themselves been implemented using the Server
066 * SDK.  As when scheduling an individual instance of these tasks, the server
067 * must be configured as follows to allow creation of third-party tasks:
068 * <PRE>
069 *   dsconfig set-global-configuration-prop
070 *     --add allowed-task:com.unboundid.directory.sdk.extensions.ThirdPartyTask
071 * </PRE>
072 * <BR><BR>
073 * The {@code Task} instance actually performs the core processing for the
074 * administrative task, while the {@code RecurringTask} instance merely ensures
075 * that the {@code Task} is scheduled with the appropriate arguments.
076 */
077@BrokerExtension()
078@Extensible()
079@DirectoryServerExtension()
080@DirectoryProxyServerExtension(appliesToLocalContent=true,
081     appliesToRemoteContent=false)
082@MetricsEngineExtension()
083@SynchronizationServerExtension(appliesToLocalContent=true,
084     appliesToSynchronizedContent=false)
085@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
086public abstract class RecurringTask
087       implements UnboundIDExtension, Reconfigurable<RecurringTaskConfig>,
088                  ExampleUsageProvider
089{
090  /**
091   * Creates a new instance of this recurring task.  All recurring task
092   * implementations must include a default constructor, but any initialization
093   * should generally be done in the {@link #initializeRecurringTask} method.
094   */
095  public RecurringTask()
096  {
097    // No implementation is required.
098  }
099
100
101
102  /**
103   * {@inheritDoc}
104   */
105  @Override()
106  public abstract String getExtensionName();
107
108
109
110  /**
111   * {@inheritDoc}
112   */
113  @Override()
114  public abstract String[] getExtensionDescription();
115
116
117
118  /**
119   * {@inheritDoc}
120   */
121  @Override()
122  public void defineConfigArguments(final ArgumentParser parser)
123         throws ArgumentException
124  {
125    // No arguments will be allowed by default.
126  }
127
128
129
130  /**
131   * Initializes this recurring task.
132   *
133   * @param  serverContext  A handle to the server context for the server in
134   *                        which this extension is running.
135   * @param  config         The general configuration for this recurring task.
136   * @param  parser         The argument parser which has been initialized from
137   *                        the configuration for this recurring task.
138   *
139   * @throws  LDAPException  If a problem occurs while initializing this
140   *                         recurring task.
141   */
142  public void initializeRecurringTask(
143                   final DirectoryServerContext serverContext,
144                   final RecurringTaskConfig config,
145                   final ArgumentParser parser)
146         throws LDAPException
147  {
148    // No initialization will be performed by default.
149  }
150
151
152
153  /**
154   * {@inheritDoc}
155   */
156  @Override()
157  public boolean isConfigurationAcceptable(final RecurringTaskConfig config,
158                      final ArgumentParser parser,
159                      final List<String> unacceptableReasons)
160  {
161    // No extended validation will be performed by default.
162    return true;
163  }
164
165
166
167  /**
168   * {@inheritDoc}
169   */
170  @Override()
171  public ResultCode applyConfiguration(final RecurringTaskConfig config,
172                                       final ArgumentParser parser,
173                                       final List<String> adminActionsRequired,
174                                       final List<String> messages)
175  {
176    // By default, no configuration changes will be applied.  If there are any
177    // arguments, then add an admin action message indicating that the extension
178    // needs to be restarted for any changes to take effect.
179    if (! parser.getNamedArguments().isEmpty())
180    {
181      adminActionsRequired.add(
182           "No configuration change has actually been applied.  The new " +
183                "configuration will not take effect until the server is " +
184                "restarted.");
185    }
186
187    return ResultCode.SUCCESS;
188  }
189
190
191
192  /**
193   * Performs any cleanup which may be necessary when this recurring task is
194   * to be taken out of service.
195   */
196  public void finalizeRecurringTask()
197  {
198    // No implementation is required.
199  }
200
201
202
203  /**
204   * Retrieves the Java class that will be used to process instances of this
205   * recurring task.
206   *
207   * @return  The java class that will be used to process instances of this
208   *          recurring task.  It must not be {@code null}.
209   */
210  public abstract Class<? extends Task> getTaskJavaClass();
211
212
213
214  /**
215   * Retrieves the list of values that should be provided to the
216   * ds-third-party-task-argument attribute for the task instance that is
217   * created.
218   *
219   * @param  scheduledStartTime  The scheduled start time that will be used for
220   *                             the task that is created.
221   * @param  lastTaskEntry       The entry for the last instance of the
222   *                             recurring task that was scheduled.  It may be
223   *                             {@code null} if the last instance is not
224   *                             available (for example, because no instances of
225   *                             the recurring task have yet been scheduled.
226   *
227   * @return  The list of values that should be provided to the
228   *          ds-third-party-task-argument for the task instance that is
229   *          created.  It may be {@code null} or empty if the task does not
230   *          require any arguments.
231   */
232  public abstract List<String> getTaskArguments(
233                                    final ZonedDateTime scheduledStartTime,
234                                    final ReadOnlyEntry lastTaskEntry);
235
236
237
238  /**
239   * {@inheritDoc}
240   */
241  @Override()
242  public Map<List<String>,String> getExamplesArgumentSets()
243  {
244    return Collections.emptyMap();
245  }
246}