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-2024 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}