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