001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2008 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import static org.opends.messages.ExtensionMessages.*;
020
021import org.forgerock.i18n.LocalizableMessage;
022import org.forgerock.i18n.slf4j.LocalizedLogger;
023
024import java.util.HashSet;
025import java.util.List;
026
027import org.forgerock.opendj.config.server.ConfigurationChangeListener;
028import org.forgerock.opendj.server.config.meta.
029       ErrorLogAccountStatusNotificationHandlerCfgDefn;
030import org.forgerock.opendj.server.config.server.AccountStatusNotificationHandlerCfg;
031import org.forgerock.opendj.server.config.server.
032       ErrorLogAccountStatusNotificationHandlerCfg;
033import org.opends.server.api.AccountStatusNotificationHandler;
034import org.forgerock.opendj.config.server.ConfigException;
035import org.opends.server.types.AccountStatusNotification;
036import org.opends.server.types.AccountStatusNotificationType;
037import org.forgerock.opendj.config.server.ConfigChangeResult;
038import org.forgerock.opendj.ldap.DN;
039import org.opends.server.types.InitializationException;
040
041/**
042 * This class defines an account status notification handler that will write
043 * information about status notifications using the Directory Server's error
044 * logging facility.
045 */
046public class ErrorLogAccountStatusNotificationHandler
047       extends
048          AccountStatusNotificationHandler
049          <ErrorLogAccountStatusNotificationHandlerCfg>
050       implements
051          ConfigurationChangeListener
052          <ErrorLogAccountStatusNotificationHandlerCfg>
053{
054  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
055
056  /**
057   * The set of names for the account status notification types that may be
058   * logged by this notification handler.
059   */
060  private static final HashSet<String> NOTIFICATION_TYPE_NAMES = new HashSet<>();
061  static
062  {
063    for (AccountStatusNotificationType t : AccountStatusNotificationType.values())
064    {
065      NOTIFICATION_TYPE_NAMES.add(t.getName());
066    }
067  }
068
069  /** The DN of the configuration entry for this notification handler. */
070  private DN configEntryDN;
071
072  /** The set of notification types that should generate log messages. */
073  private HashSet<AccountStatusNotificationType> notificationTypes;
074
075  @Override
076  public void initializeStatusNotificationHandler(
077      ErrorLogAccountStatusNotificationHandlerCfg configuration
078      )
079      throws ConfigException, InitializationException
080  {
081    configuration.addErrorLogChangeListener (this);
082    configEntryDN = configuration.dn();
083
084    // Read configuration and apply changes.
085    boolean applyChanges = true;
086    processNotificationHandlerConfig (configuration, applyChanges);
087  }
088
089  @Override
090  public void handleStatusNotification(
091                   AccountStatusNotification notification)
092  {
093    logger.info(NOTE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION,
094                  notification.getNotificationType().getName(),
095                  notification.getUserDN(),
096                  notification.getMessage().ordinal(),
097                  notification.getMessage());
098  }
099
100  @Override
101  public boolean isConfigurationAcceptable(
102                      AccountStatusNotificationHandlerCfg configuration,
103                      List<LocalizableMessage> unacceptableReasons)
104  {
105    ErrorLogAccountStatusNotificationHandlerCfg config =
106         (ErrorLogAccountStatusNotificationHandlerCfg) configuration;
107    return isConfigurationChangeAcceptable(config, unacceptableReasons);
108  }
109
110  @Override
111  public boolean isConfigurationChangeAcceptable(
112      ErrorLogAccountStatusNotificationHandlerCfg configuration,
113      List<LocalizableMessage> unacceptableReasons)
114  {
115    // Make sure that we can process the defined notification handler.
116    // If so, then we'll accept the new configuration.
117    boolean applyChanges = false;
118    return processNotificationHandlerConfig (
119        configuration, applyChanges);
120  }
121
122  /**
123   * Makes a best-effort attempt to apply the configuration contained in the
124   * provided entry.  Information about the result of this processing should be
125   * added to the provided message list.  Information should always be added to
126   * this list if a configuration change could not be applied.  If detailed
127   * results are requested, then information about the changes applied
128   * successfully (and optionally about parameters that were not changed) should
129   * also be included.
130   *
131   * @param  configuration    The entry containing the new configuration to
132   *                          apply for this component.
133   * @param  detailedResults  Indicates whether detailed information about the
134   *                          processing should be added to the list.
135   *
136   * @return  Information about the result of the configuration update.
137   */
138  public ConfigChangeResult applyConfigurationChange (
139      ErrorLogAccountStatusNotificationHandlerCfg configuration,
140      boolean detailedResults)
141  {
142    return applyConfigurationChange(configuration);
143  }
144
145  @Override
146  public ConfigChangeResult applyConfigurationChange (
147      ErrorLogAccountStatusNotificationHandlerCfg configuration
148      )
149  {
150    // Initialize the set of notification types that should generate log messages.
151    boolean applyChanges =false;
152    processNotificationHandlerConfig (configuration, applyChanges);
153
154    return new ConfigChangeResult();
155  }
156
157  /**
158   * Parses the provided configuration and configure the notification handler.
159   *
160   * @param configuration  The new configuration containing the changes.
161   * @param applyChanges   If true then take into account the new configuration.
162   *
163   * @return  The mapping between strings of character set values and the
164   *          minimum number of characters required from those sets.
165   */
166  public boolean processNotificationHandlerConfig(
167      ErrorLogAccountStatusNotificationHandlerCfg configuration,
168      boolean                                     applyChanges
169      )
170  {
171    // false if the configuration is not acceptable
172    boolean isAcceptable = true;
173
174    // The set of notification types that should generate log messages.
175    HashSet<AccountStatusNotificationType> newNotificationTypes = new HashSet<>();
176
177    // Initialize the set of notification types that should generate log messages.
178    for (ErrorLogAccountStatusNotificationHandlerCfgDefn.
179         AccountStatusNotificationType configNotificationType:
180         configuration.getAccountStatusNotificationType())
181    {
182      newNotificationTypes.add (getNotificationType (configNotificationType));
183    }
184
185    if (applyChanges && isAcceptable)
186    {
187      notificationTypes = newNotificationTypes;
188    }
189
190    return isAcceptable;
191  }
192
193  /**
194   * Gets the OpenDS notification type object that corresponds to the
195   * configuration counterpart.
196   *
197   * @param  configNotificationType  The configuration notification type for
198   *                                 which  to retrieve the OpenDS notification
199   *                                 type.
200   */
201  private AccountStatusNotificationType getNotificationType(
202      ErrorLogAccountStatusNotificationHandlerCfgDefn.
203         AccountStatusNotificationType configNotificationType
204      )
205  {
206    AccountStatusNotificationType nt = null;
207
208    switch (configNotificationType)
209    {
210    case ACCOUNT_TEMPORARILY_LOCKED:
211         nt = AccountStatusNotificationType.ACCOUNT_TEMPORARILY_LOCKED;
212         break;
213    case ACCOUNT_PERMANENTLY_LOCKED:
214         nt = AccountStatusNotificationType.ACCOUNT_PERMANENTLY_LOCKED;
215         break;
216    case ACCOUNT_UNLOCKED:
217         nt = AccountStatusNotificationType.ACCOUNT_UNLOCKED;
218         break;
219    case ACCOUNT_IDLE_LOCKED:
220         nt = AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED;
221         break;
222    case ACCOUNT_RESET_LOCKED:
223         nt = AccountStatusNotificationType.ACCOUNT_RESET_LOCKED;
224         break;
225    case ACCOUNT_DISABLED:
226         nt = AccountStatusNotificationType.ACCOUNT_DISABLED;
227         break;
228    case ACCOUNT_ENABLED:
229         nt = AccountStatusNotificationType.ACCOUNT_ENABLED;
230         break;
231    case ACCOUNT_EXPIRED:
232         nt = AccountStatusNotificationType.ACCOUNT_EXPIRED;
233         break;
234    case PASSWORD_EXPIRED:
235         nt = AccountStatusNotificationType.PASSWORD_EXPIRED;
236         break;
237    case PASSWORD_EXPIRING:
238         nt = AccountStatusNotificationType.PASSWORD_EXPIRING;
239         break;
240    case PASSWORD_RESET:
241         nt = AccountStatusNotificationType.PASSWORD_RESET;
242         break;
243    case PASSWORD_CHANGED:
244         nt = AccountStatusNotificationType.PASSWORD_CHANGED;
245         break;
246    }
247
248    return nt;
249  }
250}