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.opends.server.admin.server.ConfigurationChangeListener;
028import org.opends.server.admin.std.meta.
029       ErrorLogAccountStatusNotificationHandlerCfgDefn;
030import org.opends.server.admin.std.server.AccountStatusNotificationHandlerCfg;
031import org.opends.server.admin.std.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
055  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
056
057  /**
058   * The set of names for the account status notification types that may be
059   * logged by this notification handler.
060   */
061  private static final HashSet<String> NOTIFICATION_TYPE_NAMES = new HashSet<>();
062  static
063  {
064    for (AccountStatusNotificationType t : AccountStatusNotificationType.values())
065    {
066      NOTIFICATION_TYPE_NAMES.add(t.getName());
067    }
068  }
069
070
071  /** The DN of the configuration entry for this notification handler. */
072  private DN configEntryDN;
073
074  /** The set of notification types that should generate log messages. */
075  private HashSet<AccountStatusNotificationType> notificationTypes;
076
077
078
079  /** {@inheritDoc} */
080  public void initializeStatusNotificationHandler(
081      ErrorLogAccountStatusNotificationHandlerCfg configuration
082      )
083      throws ConfigException, InitializationException
084  {
085    configuration.addErrorLogChangeListener (this);
086    configEntryDN = configuration.dn();
087
088    // Read configuration and apply changes.
089    boolean applyChanges = true;
090    processNotificationHandlerConfig (configuration, applyChanges);
091  }
092
093
094
095  /** {@inheritDoc} */
096  public void handleStatusNotification(
097                   AccountStatusNotification notification)
098  {
099    logger.info(NOTE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION,
100                  notification.getNotificationType().getName(),
101                  notification.getUserDN(),
102                  notification.getMessage().ordinal(),
103                  notification.getMessage());
104  }
105
106
107
108  /** {@inheritDoc} */
109  @Override
110  public boolean isConfigurationAcceptable(
111                      AccountStatusNotificationHandlerCfg configuration,
112                      List<LocalizableMessage> unacceptableReasons)
113  {
114    ErrorLogAccountStatusNotificationHandlerCfg config =
115         (ErrorLogAccountStatusNotificationHandlerCfg) configuration;
116    return isConfigurationChangeAcceptable(config, unacceptableReasons);
117  }
118
119
120
121  /** {@inheritDoc} */
122  public boolean isConfigurationChangeAcceptable(
123      ErrorLogAccountStatusNotificationHandlerCfg configuration,
124      List<LocalizableMessage> unacceptableReasons)
125  {
126    // Make sure that we can process the defined notification handler.
127    // If so, then we'll accept the new configuration.
128    boolean applyChanges = false;
129    return processNotificationHandlerConfig (
130        configuration, applyChanges);
131  }
132
133
134
135  /**
136   * Makes a best-effort attempt to apply the configuration contained in the
137   * provided entry.  Information about the result of this processing should be
138   * added to the provided message list.  Information should always be added to
139   * this list if a configuration change could not be applied.  If detailed
140   * results are requested, then information about the changes applied
141   * successfully (and optionally about parameters that were not changed) should
142   * also be included.
143   *
144   * @param  configuration    The entry containing the new configuration to
145   *                          apply for this component.
146   * @param  detailedResults  Indicates whether detailed information about the
147   *                          processing should be added to the list.
148   *
149   * @return  Information about the result of the configuration update.
150   */
151  public ConfigChangeResult applyConfigurationChange (
152      ErrorLogAccountStatusNotificationHandlerCfg configuration,
153      boolean detailedResults)
154  {
155    return applyConfigurationChange(configuration);
156  }
157
158
159
160  /** {@inheritDoc} */
161  public ConfigChangeResult applyConfigurationChange (
162      ErrorLogAccountStatusNotificationHandlerCfg configuration
163      )
164  {
165    // Initialize the set of notification types that should generate log messages.
166    boolean applyChanges =false;
167    processNotificationHandlerConfig (configuration, applyChanges);
168
169    return new ConfigChangeResult();
170  }
171
172
173  /**
174   * Parses the provided configuration and configure the notification handler.
175   *
176   * @param configuration  The new configuration containing the changes.
177   * @param applyChanges   If true then take into account the new configuration.
178   *
179   * @return  The mapping between strings of character set values and the
180   *          minimum number of characters required from those sets.
181   */
182  public boolean processNotificationHandlerConfig(
183      ErrorLogAccountStatusNotificationHandlerCfg configuration,
184      boolean                                     applyChanges
185      )
186  {
187    // false if the configuration is not acceptable
188    boolean isAcceptable = true;
189
190    // The set of notification types that should generate log messages.
191    HashSet<AccountStatusNotificationType> newNotificationTypes = new HashSet<>();
192
193    // Initialize the set of notification types that should generate log messages.
194    for (ErrorLogAccountStatusNotificationHandlerCfgDefn.
195         AccountStatusNotificationType configNotificationType:
196         configuration.getAccountStatusNotificationType())
197    {
198      newNotificationTypes.add (getNotificationType (configNotificationType));
199    }
200
201    if (applyChanges && isAcceptable)
202    {
203      notificationTypes = newNotificationTypes;
204    }
205
206    return isAcceptable;
207  }
208
209
210  /**
211   * Gets the OpenDS notification type object that corresponds to the
212   * configuration counterpart.
213   *
214   * @param  configNotificationType  The configuration notification type for
215   *                                 which  to retrieve the OpenDS notification
216   *                                 type.
217   */
218  private AccountStatusNotificationType getNotificationType(
219      ErrorLogAccountStatusNotificationHandlerCfgDefn.
220         AccountStatusNotificationType configNotificationType
221      )
222  {
223    AccountStatusNotificationType nt = null;
224
225    switch (configNotificationType)
226    {
227    case ACCOUNT_TEMPORARILY_LOCKED:
228         nt = AccountStatusNotificationType.ACCOUNT_TEMPORARILY_LOCKED;
229         break;
230    case ACCOUNT_PERMANENTLY_LOCKED:
231         nt = AccountStatusNotificationType.ACCOUNT_PERMANENTLY_LOCKED;
232         break;
233    case ACCOUNT_UNLOCKED:
234         nt = AccountStatusNotificationType.ACCOUNT_UNLOCKED;
235         break;
236    case ACCOUNT_IDLE_LOCKED:
237         nt = AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED;
238         break;
239    case ACCOUNT_RESET_LOCKED:
240         nt = AccountStatusNotificationType.ACCOUNT_RESET_LOCKED;
241         break;
242    case ACCOUNT_DISABLED:
243         nt = AccountStatusNotificationType.ACCOUNT_DISABLED;
244         break;
245    case ACCOUNT_ENABLED:
246         nt = AccountStatusNotificationType.ACCOUNT_ENABLED;
247         break;
248    case ACCOUNT_EXPIRED:
249         nt = AccountStatusNotificationType.ACCOUNT_EXPIRED;
250         break;
251    case PASSWORD_EXPIRED:
252         nt = AccountStatusNotificationType.PASSWORD_EXPIRED;
253         break;
254    case PASSWORD_EXPIRING:
255         nt = AccountStatusNotificationType.PASSWORD_EXPIRING;
256         break;
257    case PASSWORD_RESET:
258         nt = AccountStatusNotificationType.PASSWORD_RESET;
259         break;
260    case PASSWORD_CHANGED:
261         nt = AccountStatusNotificationType.PASSWORD_CHANGED;
262         break;
263    }
264
265    return nt;
266  }
267
268}
269