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 2010-2024 Ping Identity Corporation 026 */ 027package com.unboundid.directory.sdk.ds.api; 028 029 030 031import java.util.Collections; 032import java.util.List; 033import java.util.Map; 034 035import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider; 036import com.unboundid.directory.sdk.common.internal.Reconfigurable; 037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension; 038import com.unboundid.directory.sdk.ds.config. 039 AccountStatusNotificationHandlerConfig; 040import com.unboundid.directory.sdk.ds.types.AccountStatusNotification; 041import com.unboundid.directory.sdk.ds.types.DirectoryServerContext; 042import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension; 043import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension; 044import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension; 045import com.unboundid.ldap.sdk.LDAPException; 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 which have 057 * the ability to process notifications about events that occur that could 058 * change the status of a user account. For example, account status 059 * notification handlers may be used to notify the end user and/or 060 * administrators of a change to that user's account. The kinds of events that 061 * may trigger account status notifications are defined in the 062 * {@link com.unboundid.directory.sdk.ds.types.AccountStatusNotificationType} 063 * enum, and include things like user accounts locked due to authentication 064 * failures, password expiration errors and warnings, and administrative 065 * password resets. 066 * <BR> 067 * <H2>Configuring Account Status Notification Handlers</H2> 068 * In order to configure an account status notification handler created using 069 * this API, use a command like: 070 * <PRE> 071 * dsconfig create-account-status-notification-handler \ 072 * --handler-name "<I>{handler-name}</I>" \ 073 * --type third-party \ 074 * --set enabled:true \ 075 * --set "extension-class:<I>{class-name}</I>" \ 076 * --set "extension-argument:<I>{name=value}</I>" 077 * </PRE> 078 * where "<I>{handler-name}</I>" is the name to use for the account status 079 * notification handler instance, "<I>{class-name}</I>" is the fully-qualified 080 * name of the Java class that extends 081 * {@code com.unboundid.directory.sdk.ds.api.AccountStatusNotificationHandler}, 082 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to 083 * provide to the account status notification handler. If multiple arguments 084 * should be provided to the handler, then the 085 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be 086 * provided multiple times. 087 */ 088@Extensible() 089@DirectoryServerExtension() 090@DirectoryProxyServerExtension(appliesToLocalContent=true, 091 appliesToRemoteContent=false) 092@SynchronizationServerExtension(appliesToLocalContent=true, 093 appliesToSynchronizedContent=false) 094@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE) 095public abstract class AccountStatusNotificationHandler 096 implements UnboundIDExtension, 097 Reconfigurable<AccountStatusNotificationHandlerConfig>, 098 ExampleUsageProvider 099{ 100 /** 101 * Creates a new instance of this account status notification handler. All 102 * account status notification handler implementations must include a default 103 * constructor, but any initialization should generally be done in the 104 * {@code initializeAccountStatusNotificationHandler} method. 105 */ 106 public AccountStatusNotificationHandler() 107 { 108 // No implementation is required. 109 } 110 111 112 113 /** 114 * {@inheritDoc} 115 */ 116 public abstract String getExtensionName(); 117 118 119 120 /** 121 * {@inheritDoc} 122 */ 123 public abstract String[] getExtensionDescription(); 124 125 126 127 /** 128 * {@inheritDoc} 129 */ 130 public void defineConfigArguments(final ArgumentParser parser) 131 throws ArgumentException 132 { 133 // No arguments will be allowed by default. 134 } 135 136 137 138 /** 139 * Initializes this account status notification handler. 140 * 141 * @param serverContext A handle to the server context for the server in 142 * which this extension is running. 143 * @param config The general configuration for this account status 144 * notification handler. 145 * @param parser The argument parser which has been initialized from 146 * the configuration for this account status 147 * notification handler. 148 * 149 * @throws LDAPException If a problem occurs while initializing this account 150 * status notificationHandler. 151 */ 152 public void initializeAccountStatusNotificationHandler( 153 final DirectoryServerContext serverContext, 154 final AccountStatusNotificationHandlerConfig config, 155 final ArgumentParser parser) 156 throws LDAPException 157 { 158 // No initialization will be performed by default. 159 } 160 161 162 163 /** 164 * {@inheritDoc} 165 */ 166 public boolean isConfigurationAcceptable( 167 final AccountStatusNotificationHandlerConfig config, 168 final ArgumentParser parser, 169 final List<String> unacceptableReasons) 170 { 171 // No extended validation will be performed by default. 172 return true; 173 } 174 175 176 177 /** 178 * {@inheritDoc} 179 */ 180 public ResultCode applyConfiguration( 181 final AccountStatusNotificationHandlerConfig config, 182 final ArgumentParser parser, 183 final List<String> adminActionsRequired, 184 final List<String> messages) 185 { 186 // By default, no configuration changes will be applied. If there are any 187 // arguments, then add an admin action message indicating that the extension 188 // needs to be restarted for any changes to take effect. 189 if (! parser.getNamedArguments().isEmpty()) 190 { 191 adminActionsRequired.add( 192 "No configuration change has actually been applied. The new " + 193 "configuration will not take effect until this account " + 194 "status notification handler is disabled and re-enabled or " + 195 "until the server is restarted."); 196 } 197 198 return ResultCode.SUCCESS; 199 } 200 201 202 203 /** 204 * Performs any cleanup which may be necessary when this account status 205 * notification handler is to be taken out of service. 206 */ 207 public void finalizeAccountStatusNotificationHandler() 208 { 209 // No implementation is required. 210 } 211 212 213 214 /** 215 * Performs any processing that may be necessary in conjunction with the 216 * provided account status notification. 217 * 218 * @param notification The account status notification to be processed. 219 */ 220 public abstract void handleStatusNotification( 221 final AccountStatusNotification notification); 222 223 224 225 /** 226 * {@inheritDoc} 227 */ 228 public Map<List<String>,String> getExamplesArgumentSets() 229 { 230 return Collections.emptyMap(); 231 } 232}