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