mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
26.35.2007 dfdd9440011d222f12e6e336ed6ab6e59ee2be4b
opends/src/server/org/opends/server/api/AccountStatusNotificationHandler.java
@@ -25,18 +25,16 @@
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.api;
import org.opends.messages.Message;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.
       AccountStatusNotificationHandlerCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationType;
import org.opends.server.types.DN;
import org.opends.server.types.InitializationException;
@@ -133,35 +131,12 @@
  /**
   * Performs any processing that may be necessary in conjunction with
   * the provided account status notification type.
   *
   * @param  notificationType  The type for this account status
   *                           notification.
   * @param  userDN            The DN of the user entry to which this
   *                           notification applies.
   * @param  message           The human-readable message for this
   *                           notification.
   */
  public abstract void
       handleStatusNotification(
          AccountStatusNotificationType notificationType,
          DN userDN, Message message);
  /**
   * Performs any processing that may be necessary in conjunction with
   * the provided account status notification.
   *
   * @param  notification  The account status notification to be
   *                       processed.
   */
  public void handleStatusNotification(
                   AccountStatusNotification notification)
  {
    handleStatusNotification(notification.getNotificationType(),
                             notification.getUserDN(),
                             notification.getMessage());
  }
  public abstract void handleStatusNotification(
                            AccountStatusNotification notification);
}
opends/src/server/org/opends/server/core/PasswordPolicyState.java
@@ -25,8 +25,7 @@
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import java.text.SimpleDateFormat;
@@ -38,9 +37,12 @@
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
import org.opends.server.admin.std.server.PasswordValidatorCfg;
import org.opends.server.api.AccountStatusNotificationHandler;
@@ -55,6 +57,7 @@
import org.opends.server.schema.GeneralizedTimeSyntax;
import org.opends.server.schema.UserPasswordSyntax;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationProperty;
import org.opends.server.types.AccountStatusNotificationType;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
@@ -4596,27 +4599,22 @@
  /**
   * Generates an account status notification for this user.
   *
   * @param  notificationType  The type for the account status notification.
   * @param  userDN            The DN of the user entry to which this
   *                           notification applies.
   * @param  message           The human-readable message for the notification.
   * @param  notificationType        The type for the account status
   *                                 notification.
   * @param  userEntry               The entry for the user to which this
   *                                 notification applies.
   * @param  message                 The human-readable message for the
   *                                 notification.
   * @param  notificationProperties  The set of properties for the notification.
   */
  public void generateAccountStatusNotification(
          AccountStatusNotificationType notificationType,
          DN userDN, Message message)
          Entry userEntry, Message message,
          Map<AccountStatusNotificationProperty,List<String>>
               notificationProperties)
  {
    Collection<AccountStatusNotificationHandler> handlers =
         passwordPolicy.getAccountStatusNotificationHandlers().values();
    if ((handlers == null) || handlers.isEmpty())
    {
      return;
    }
    for (AccountStatusNotificationHandler handler : handlers)
    {
      handler.handleStatusNotification(notificationType, userDN,
              message);
    }
    generateAccountStatusNotification(new AccountStatusNotification(
         notificationType, userEntry, message, notificationProperties));
  }
opends/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandler.java
@@ -45,11 +45,10 @@
       ErrorLogAccountStatusNotificationHandlerCfg;
import org.opends.server.api.AccountStatusNotificationHandler;
import org.opends.server.config.ConfigException;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationType;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
@@ -72,15 +71,15 @@
   * The set of names for the account status notification types that may be
   * logged by this notification handler.
   */
  private static final HashSet<Message> NOTIFICATION_TYPE_NAMES =
       new HashSet<Message>();
  private static final HashSet<String> NOTIFICATION_TYPE_NAMES =
       new HashSet<String>();
  static
  {
    for (AccountStatusNotificationType t :
         AccountStatusNotificationType.values())
    {
      NOTIFICATION_TYPE_NAMES.add(t.getNotificationName());
      NOTIFICATION_TYPE_NAMES.add(t.getName());
    }
  }
@@ -114,17 +113,14 @@
  /**
   * {@inheritDoc}
   */
  public void handleStatusNotification(AccountStatusNotificationType
          notificationType,
                                       DN userDN, Message message)
  public void handleStatusNotification(
                   AccountStatusNotification notification)
  {
    if (notificationTypes.contains(notificationType))
    {
      logError(NOTE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION.get(
                notificationType.getNotificationName(),
                String.valueOf(userDN),
                message.getDescriptor().getId(), message));
    }
    logError(NOTE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION.get(
                  notification.getNotificationType().getName(),
                  String.valueOf(notification.getUserDN()),
                  notification.getMessage().getDescriptor().getId(),
                  notification.getMessage()));
  }
opends/src/server/org/opends/server/types/AccountStatusNotification.java
@@ -25,10 +25,24 @@
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import org.opends.messages.Message;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opends.messages.Message;
import org.opends.server.core.PasswordPolicy;
import org.opends.server.core.PasswordPolicyState;
import static org.opends.server.types.
                   AccountStatusNotificationProperty.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a data type for storing information associated
@@ -36,7 +50,7 @@
 */
@org.opends.server.types.PublicAPI(
     stability=org.opends.server.types.StabilityLevel.VOLATILE,
     mayInstantiate=true,
     mayInstantiate=false,
     mayExtend=false,
     mayInvoke=true)
public final class AccountStatusNotification
@@ -44,8 +58,13 @@
  // The notification type for this account status notification.
  private AccountStatusNotificationType notificationType;
  // The DN of the user entry to which this notification applies.
  private DN userDN;
  // The entry for the user to whom this notification applies.
  private Entry userEntry;
  // A set of additional properties that may be useful for this
  // notification.
  private Map<AccountStatusNotificationProperty,List<String>>
               notificationProperties;
  // A message that provides additional information for this account
  // status notification.
@@ -57,20 +76,36 @@
   * Creates a new account status notification object with the
   * provided information.
   *
   * @param  notificationType  The type for this account status
   *                           notification.
   * @param  userDN            The DN of the user entry to which
   *                           this notification applies.
   * @param  message           The human-readable message for this
   *                           notification.
   * @param  notificationType        The type for this account status
   *                                 notification.
   * @param  userEntry               The entry for the user to whom
   *                                 this notification applies.
   * @param  message                 The human-readable message for
   *                                 this notification.
   * @param  notificationProperties  A set of properties that may
   *                                 include additional information
   *                                 about this notification.
   */
  public AccountStatusNotification(
              AccountStatusNotificationType notificationType,
              DN userDN, Message message)
              Entry userEntry, Message message,
              Map<AccountStatusNotificationProperty,List<String>>
                   notificationProperties)
  {
    this.notificationType = notificationType;
    this.userDN           = userDN;
    this.userEntry        = userEntry;
    this.message          = message;
    if (notificationProperties == null)
    {
      this.notificationProperties =
           new HashMap<AccountStatusNotificationProperty,
                       List<String>>(0);
    }
    else
    {
      this.notificationProperties = notificationProperties;
    }
  }
@@ -98,7 +133,19 @@
   */
  public DN getUserDN()
  {
    return userDN;
    return userEntry.getDN();
  }
  /**
   * Retrieves user entry for whom this notification applies.
   *
   * @return  The user entry for whom this notification applies.
   */
  public Entry getUserEntry()
  {
    return userEntry;
  }
@@ -118,6 +165,131 @@
  /**
   * Retrieves a set of properties that may provide additional
   * information for this account status notification.
   *
   * @return  A set of properties that may provide additional
   *          information for this account status notification.
   */
  public Map<AccountStatusNotificationProperty,List<String>>
              getNotificationProperties()
  {
    return notificationProperties;
  }
  /**
   * Creates a set of account status notification properties from the
   * provided information.
   *
   * @param  pwPolicyState     The password policy state for the user
   *                           associated with the notification.
   * @param  tempLocked        Indicates whether the user's account
   *                           has been temporarily locked.
   * @param  timeToExpiration  The length of time in seconds until the
   *                           user's password expires, or -1 if it's
   *                           not about to expire.
   * @param  oldPasswords      The set of old passwords for the user,
   *                           or {@code null} if this is not
   *                           applicable.
   * @param  newPasswords      The set of new passwords for the user,
   *                           or {@code null} if this is not
   *                           applicable.
   *
   * @return  The created set of account status notification
   *          properties.
   */
  @org.opends.server.types.PublicAPI(
       stability=org.opends.server.types.StabilityLevel.PRIVATE,
       mayInstantiate=false,
       mayExtend=false,
       mayInvoke=false)
  public static Map<AccountStatusNotificationProperty,List<String>>
                     createProperties(
                          PasswordPolicyState pwPolicyState,
                          boolean tempLocked, int timeToExpiration,
                          List<AttributeValue> oldPasswords,
                          List<AttributeValue> newPasswords)
  {
    HashMap<AccountStatusNotificationProperty,List<String>> props =
         new HashMap<AccountStatusNotificationProperty,
                     List<String>>(4);
    PasswordPolicy policy = pwPolicyState.getPolicy();
    ArrayList<String> propList = new ArrayList<String>(1);
    propList.add(policy.getConfigEntryDN().toString());
    props.put(PASSWORD_POLICY_DN, propList);
    if (tempLocked)
    {
      int secondsUntilUnlock = policy.getLockoutDuration();
      if (secondsUntilUnlock > 0)
      {
        propList = new ArrayList<String>(1);
        propList.add(String.valueOf(secondsUntilUnlock));
        props.put(SECONDS_UNTIL_UNLOCK, propList);
        propList = new ArrayList<String>(1);
        propList.add(
             secondsToTimeString(secondsUntilUnlock).toString());
        props.put(TIME_UNTIL_UNLOCK, propList);
        long unlockTime = System.currentTimeMillis() +
                          (1000*secondsUntilUnlock);
        propList = new ArrayList<String>(1);
        propList.add(new Date(unlockTime).toString());
        props.put(ACCOUNT_UNLOCK_TIME, propList);
      }
    }
    if (timeToExpiration >= 0)
    {
        propList = new ArrayList<String>(1);
        propList.add(String.valueOf(timeToExpiration));
        props.put(SECONDS_UNTIL_EXPIRATION, propList);
        propList = new ArrayList<String>(1);
        propList.add(
             secondsToTimeString(timeToExpiration).toString());
        props.put(TIME_UNTIL_EXPIRATION, propList);
        long expTime = System.currentTimeMillis() +
                       (1000*timeToExpiration);
        propList = new ArrayList<String>(1);
        propList.add(new Date(expTime).toString());
        props.put(ACCOUNT_UNLOCK_TIME, propList);
    }
    if ((oldPasswords != null) && (! oldPasswords.isEmpty()))
    {
      propList = new ArrayList<String>(oldPasswords.size());
      for (AttributeValue v : oldPasswords)
      {
        propList.add(v.getStringValue());
      }
      props.put(OLD_PASSWORD, propList);
    }
    if ((newPasswords != null) && (! newPasswords.isEmpty()))
    {
      propList = new ArrayList<String>(newPasswords.size());
      for (AttributeValue v : newPasswords)
      {
        propList.add(v.getStringValue());
      }
      props.put(NEW_PASSWORD, propList);
    }
    return props;
  }
  /**
   * Retrieves a string representation of this account status
   * notification.
   *
@@ -127,8 +299,8 @@
  public String toString()
  {
    return "AccountStatusNotification(type=" +
           notificationType.getNotificationName() + ",dn=" +
           userDN + ",message=" + message + ")";
           notificationType.getName() + ",dn=" + userEntry.getDN() +
           ",message=" + message + ")";
  }
}
opends/src/server/org/opends/server/types/AccountStatusNotificationProperty.java
New file
@@ -0,0 +1,235 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class implements an enumeration that holds the possible set of
 * additional properties that can be included in an account status
 * notification.
 */
@org.opends.server.types.PublicAPI(
     stability=org.opends.server.types.StabilityLevel.VOLATILE,
     mayInstantiate=false,
     mayExtend=false,
     mayInvoke=true)
public enum AccountStatusNotificationProperty
{
  /**
   * The property whose value will be the string representation of the
   * DN of the password policy for the target user.  This will be
   * available for all notification types.
   */
  PASSWORD_POLICY_DN("password-policy-dn"),
  /**
   * The property whose value will be a generalized time
   * representation of the time at which the user's account will be
   * unlocked.  This will be available for the
   * {@code ACCOUNT_TEMPORARILY_LOCKED} notification type.
   */
  ACCOUNT_UNLOCK_TIME("account-unlock-time"),
  /**
   * The property whose value will be the number of seconds until the
   * user's account is unlocked.  This will be available for the
   * {@code ACCOUNT_TEMPORARILY_LOCKED} notification type.
   */
  SECONDS_UNTIL_UNLOCK("seconds-until-unlock"),
  /**
   * The property whose value will be a localized, human-readable
   * representation of the length of time until the user's account is
   * unlocked.  This will be available for the
   * {@code ACCOUNT_TEMPORARILY_LOCKED} notification type.
   */
  TIME_UNTIL_UNLOCK("time-until-unlock"),
  /**
   * The property whose value will be the generalized time
   * representation of the time that the user's password will expire.
   * This will be available for the {@code PASSWORD_EXPIRING}
   * notification type.
   */
  PASSWORD_EXPIRATION_TIME("password-expiration-time"),
  /**
   * The property whose value will be the number of seconds until the
   * user's password expires.  This will be available for the
   * {@code PASSWORD_EXPIRING} notification type.
   */
  SECONDS_UNTIL_EXPIRATION("seconds-until-expiration"),
  /**
   * The property whose value will be a localized, human-readable
   * representation of the length of time until the user's password
   * expires.  This will be available for the
   * {@code PASSWORD_EXPIRING} notification type.
   */
  TIME_UNTIL_EXPIRATION("time-unti-expiration"),
  /**
   * The property whose value will be a clear-text representation of
   * the user's old password.  This may be available for the
   * {@code PASSWORD_RESET} and {@code PASSWORD_CHANGED} notification
   * types.
   */
  OLD_PASSWORD("old-password"),
  /**
   * The property whose value will be a clear-text representation of
   * the user's new password.  This may be available for the
   * {@code PASSWORD_RESET} and {@code PASSWORD_CHANGED} notification
   * types.
   */
  NEW_PASSWORD("new-password");
  // The notification type name.
  private String name;
  /**
   * Creates a new account status notification property with the
   * provided name.
   *
   * @param  name  The name for this account status notification
   *               property.
   */
  private AccountStatusNotificationProperty(String name)
  {
    this.name = name;
  }
  /**
   * Retrieves the account status notification type with the specified
   * name.
   *
   * @param  name  The name for the account status notification type
   *               to retrieve.
   *
   * @return  The requested account status notification type, or
   *          <CODE>null</CODE> if there is no type with the given
   *          name.
   */
  public static AccountStatusNotificationProperty forName(String name)
  {
    String lowerName = toLowerCase(name);
    if (lowerName.equals("password-policy-dn"))
    {
      return PASSWORD_POLICY_DN;
    }
    else if (lowerName.equals("account-unlock-time"))
    {
      return ACCOUNT_UNLOCK_TIME;
    }
    else if (lowerName.equals("seconds-until-unlock"))
    {
      return SECONDS_UNTIL_UNLOCK;
    }
    else if (lowerName.equals("time-until-unlock"))
    {
      return TIME_UNTIL_UNLOCK;
    }
    else if (lowerName.equals("password-expiration-time"))
    {
      return PASSWORD_EXPIRATION_TIME;
    }
    else if (lowerName.equals("seconds-until-expiration"))
    {
      return SECONDS_UNTIL_EXPIRATION;
    }
    else if (lowerName.equals("time-until-expiration"))
    {
      return TIME_UNTIL_EXPIRATION;
    }
    else if (lowerName.equals("old-password"))
    {
      return OLD_PASSWORD;
    }
    else if (lowerName.equals("new-password"))
    {
      return NEW_PASSWORD;
    }
    else
    {
      return null;
    }
  }
  /**
   * Retrieves the name for this account status notification property.
   *
   * @return  The name for this account status notification property.
   */
  public String getName()
  {
    return name;
  }
  /**
   * Retrieves a string representation of this account status
   * notification property.
   *
   * @return  A string representation of this account status
   *          notification property.
   */
  public String toString()
  {
    return name;
  }
}
opends/src/server/org/opends/server/types/AccountStatusNotificationType.java
@@ -25,13 +25,9 @@
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import org.opends.messages.Message;
import org.opends.messages.MessageDescriptor;
import static org.opends.messages.UtilityMessages.*;
import static org.opends.server.util.StaticUtils.*;
@@ -52,8 +48,7 @@
   * whenever a user account has been temporarily locked after too
   * many failed attempts.
   */
  ACCOUNT_TEMPORARILY_LOCKED(
       INFO_ACCTNOTTYPE_ACCOUNT_TEMPORARILY_LOCKED.get()),
  ACCOUNT_TEMPORARILY_LOCKED("account-temporarily-locked"),
@@ -63,7 +58,7 @@
   * many failed attempts.
   */
  ACCOUNT_PERMANENTLY_LOCKED(
       INFO_ACCTNOTTYPE_ACCOUNT_PERMANENTLY_LOCKED.get()),
       "account-permanently-locked"),
@@ -71,7 +66,7 @@
   * Indicates that an account status message should be generated
   * whenever a user account has been unlocked by an administrator.
   */
  ACCOUNT_UNLOCKED(INFO_ACCTNOTTYPE_ACCOUNT_UNLOCKED.get()),
  ACCOUNT_UNLOCKED("account-unlocked"),
@@ -80,7 +75,7 @@
   * whenever a user account has been locked because it was idle for
   * too long.
   */
  ACCOUNT_IDLE_LOCKED(INFO_ACCTNOTTYPE_ACCOUNT_IDLE_LOCKED.get()),
  ACCOUNT_IDLE_LOCKED("account-idle-locked"),
@@ -90,7 +85,7 @@
   * had been reset by an administrator but not changed by the user
   * within the required interval.
   */
  ACCOUNT_RESET_LOCKED(INFO_ACCTNOTTYPE_ACCOUNT_RESET_LOCKED.get()),
  ACCOUNT_RESET_LOCKED("account-reset-locked"),
@@ -98,7 +93,7 @@
   * Indicates that an account status message should be generated
   * whenever a user account has been disabled by an administrator.
   */
  ACCOUNT_DISABLED(INFO_ACCTNOTTYPE_ACCOUNT_DISABLED.get()),
  ACCOUNT_DISABLED("account-disabled"),
@@ -106,7 +101,7 @@
   * Indicates that an account status message should be generated
   * whenever a user account has been enabled by an administrator.
   */
  ACCOUNT_ENABLED(INFO_ACCTNOTTYPE_ACCOUNT_ENABLED.get()),
  ACCOUNT_ENABLED("account-enabled"),
@@ -115,7 +110,7 @@
   * whenever a user authentication has failed because the account
   * has expired.
   */
  ACCOUNT_EXPIRED(INFO_ACCTNOTTYPE_ACCOUNT_EXPIRED.get()),
  ACCOUNT_EXPIRED("account-expired"),
@@ -124,7 +119,7 @@
   * generated whenever a user authentication has failed because the
   * password has expired.
   */
  PASSWORD_EXPIRED(INFO_ACCTNOTTYPE_PASSWORD_EXPIRED.get()),
  PASSWORD_EXPIRED("password-expired"),
@@ -134,7 +129,7 @@
   * generated the first time that a password expiration warning is
   * encountered for a user password.
   */
  PASSWORD_EXPIRING(INFO_ACCTNOTTYPE_PASSWORD_EXPIRING.get()),
  PASSWORD_EXPIRING("password-expiring"),
@@ -143,7 +138,7 @@
   * generated whenever a user's password is reset by an
   * administrator.
   */
  PASSWORD_RESET(INFO_ACCTNOTTYPE_PASSWORD_RESET.get()),
  PASSWORD_RESET("password-reset"),
@@ -151,72 +146,24 @@
   * Indicates whether an account status notification message should
   * be generated whenever a user changes his/her own password.
   */
  PASSWORD_CHANGED(INFO_ACCTNOTTYPE_PASSWORD_CHANGED.get());
  PASSWORD_CHANGED("password-changed");
  // The notification type message.
  private Message notificationName;
  // The notification type name.
  private String name;
  /**
   * Creates a new account status notification type with the provided
   * notification type ID.
   * name.
   *
   * @param  notification      The notification message for
   *                           this account status notification.
   * @param  name  The name for this account status notification type.
   */
  private AccountStatusNotificationType(Message notification)
  private AccountStatusNotificationType(String name)
  {
    this.notificationName = notification;
  }
  /**
   * Retrieves the account status notification type with the specified
   * notification type identifier.
   *
   * @param  notification    The notification type message for
   *                         the notification type to retrieve.
   *
   * @return  The requested account status notification type, or
   *          <CODE>null</CODE> if there is no type for the given
   *          notification type identifier.
   */
  public static AccountStatusNotificationType
                     typeForMessage(Message notification)
  {
    MessageDescriptor md = notification.getDescriptor();
    if (INFO_ACCTNOTTYPE_ACCOUNT_TEMPORARILY_LOCKED.equals(md)) {
      return ACCOUNT_TEMPORARILY_LOCKED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_PERMANENTLY_LOCKED
            .equals(md)) {
      return ACCOUNT_PERMANENTLY_LOCKED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_UNLOCKED.equals(md)) {
      return ACCOUNT_UNLOCKED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_IDLE_LOCKED.equals(md)) {
      return ACCOUNT_IDLE_LOCKED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_RESET_LOCKED.equals(md)) {
      return ACCOUNT_RESET_LOCKED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_DISABLED.equals(md)) {
      return ACCOUNT_DISABLED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_ENABLED.equals(md)) {
      return ACCOUNT_ENABLED;
    } else if (INFO_ACCTNOTTYPE_ACCOUNT_EXPIRED.equals(md)) {
      return ACCOUNT_EXPIRED;
    } else if (INFO_ACCTNOTTYPE_PASSWORD_EXPIRED.equals(md)) {
      return PASSWORD_EXPIRED;
    } else if (INFO_ACCTNOTTYPE_PASSWORD_EXPIRING.equals(md)) {
      return PASSWORD_EXPIRING;
    } else if (INFO_ACCTNOTTYPE_PASSWORD_RESET.equals(md)) {
      return PASSWORD_RESET;
    } else if (INFO_ACCTNOTTYPE_PASSWORD_CHANGED.equals(md)) {
      return PASSWORD_CHANGED;
    } else {
      return null;
    }
    this.name = name;
  }
@@ -234,65 +181,52 @@
   */
  public static AccountStatusNotificationType typeForName(String name)
  {
    Message lowerName = Message.raw(toLowerCase(name));
    if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_TEMPORARILY_LOCKED.get()))
    String lowerName = toLowerCase(name);
    if (lowerName.equals("account-temporarily-locked"))
    {
      return ACCOUNT_TEMPORARILY_LOCKED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_PERMANENTLY_LOCKED.get()))
    else if (lowerName.equals("account-permanently-locked"))
    {
      return ACCOUNT_PERMANENTLY_LOCKED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_UNLOCKED.get()))
    else if (lowerName.equals("account-unlocked"))
    {
      return ACCOUNT_UNLOCKED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_IDLE_LOCKED.get()))
    else if (lowerName.equals("account-idle-locked"))
    {
      return ACCOUNT_IDLE_LOCKED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_RESET_LOCKED.get()))
    else if (lowerName.equals("account-reset-locked"))
    {
      return ACCOUNT_RESET_LOCKED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_DISABLED.get()))
    else if (lowerName.equals("account-disabled"))
    {
      return ACCOUNT_DISABLED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_ENABLED.get()))
    else if (lowerName.equals("account-enabled"))
    {
      return ACCOUNT_ENABLED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_ACCOUNT_EXPIRED.get()))
    else if (lowerName.equals("account-expired"))
    {
      return ACCOUNT_EXPIRED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_PASSWORD_EXPIRED.get()))
    else if (lowerName.equals("password-expired"))
    {
      return PASSWORD_EXPIRED;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_PASSWORD_EXPIRING.get()))
    else if (lowerName.equals("password-expiring"))
    {
      return PASSWORD_EXPIRING;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_PASSWORD_RESET.get()))
    else if (lowerName.equals("password-reset"))
    {
      return PASSWORD_RESET;
    }
    else if (lowerName.equals(
            INFO_ACCTNOTTYPE_PASSWORD_CHANGED.get()))
    else if (lowerName.equals("password-changed"))
    {
      return PASSWORD_CHANGED;
    }
@@ -309,9 +243,9 @@
   *
   * @return  The name for this account status notification type.
   */
  public Message getNotificationName()
  public String getName()
  {
    return notificationName;
    return name;
  }
@@ -325,7 +259,7 @@
   */
  public String toString()
  {
    return String.valueOf(getNotificationName());
    return name;
  }
}
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -94,6 +94,7 @@
import org.opends.server.schema.BooleanSyntax;
import org.opends.server.schema.UserPasswordSyntax;
import org.opends.server.types.AcceptRejectWarn;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationType;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
@@ -2180,15 +2181,21 @@
                Message message = INFO_MODIFY_PASSWORD_CHANGED.get();
                pwPolicyState.generateAccountStatusNotification(
                    AccountStatusNotificationType.PASSWORD_CHANGED, entryDN,
                    message);
                    AccountStatusNotificationType.PASSWORD_CHANGED,
                    modifiedEntry, message,
                    AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, localOp.getCurrentPasswords(),
                         localOp.getNewPasswords()));
              }
              else
              {
                Message message = INFO_MODIFY_PASSWORD_RESET.get();
                pwPolicyState.generateAccountStatusNotification(
                    AccountStatusNotificationType.PASSWORD_RESET, entryDN,
                    message);
                    AccountStatusNotificationType.PASSWORD_RESET, modifiedEntry,
                    message,
                    AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, localOp.getCurrentPasswords(),
                         localOp.getNewPasswords()));
              }
            }
@@ -2198,15 +2205,19 @@
              {
                Message message = INFO_MODIFY_ACCOUNT_ENABLED.get();
                pwPolicyState.generateAccountStatusNotification(
                    AccountStatusNotificationType.ACCOUNT_ENABLED, entryDN,
                    message);
                    AccountStatusNotificationType.ACCOUNT_ENABLED,
                    modifiedEntry, message,
                    AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              }
              else
              {
                Message message = INFO_MODIFY_ACCOUNT_DISABLED.get();
                pwPolicyState.generateAccountStatusNotification(
                    AccountStatusNotificationType.ACCOUNT_DISABLED, entryDN,
                    message);
                    AccountStatusNotificationType.ACCOUNT_DISABLED,
                    modifiedEntry, message,
                    AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              }
            }
@@ -2214,8 +2225,10 @@
            {
              Message message = INFO_MODIFY_ACCOUNT_UNLOCKED.get();
              pwPolicyState.generateAccountStatusNotification(
                  AccountStatusNotificationType.ACCOUNT_UNLOCKED, entryDN,
                  message);
                  AccountStatusNotificationType.ACCOUNT_UNLOCKED, modifiedEntry,
                  message,
                  AccountStatusNotification.createProperties(pwPolicyState,
                       false, -1, null, null));
            }
          }
@@ -3384,8 +3397,10 @@
              localOp.setAuthFailureReason(message);
              pwPolicyState.generateAccountStatusNotification(
                   AccountStatusNotificationType.ACCOUNT_EXPIRED, bindDN,
                      message);
                   AccountStatusNotificationType.ACCOUNT_EXPIRED, userEntry,
                   message,
                   AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              break bindProcessing;
            }
@@ -3417,8 +3432,10 @@
              localOp.setAuthFailureReason(message);
              pwPolicyState.generateAccountStatusNotification(
                   AccountStatusNotificationType.ACCOUNT_RESET_LOCKED, bindDN,
                      message);
                   AccountStatusNotificationType.ACCOUNT_RESET_LOCKED,
                   userEntry, message,
                   AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              break bindProcessing;
            }
@@ -3436,8 +3453,10 @@
              localOp.setAuthFailureReason(message);
              pwPolicyState.generateAccountStatusNotification(
                   AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED, bindDN,
                      message);
                   AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED, userEntry,
                   message,
                   AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              break bindProcessing;
            }
@@ -3479,8 +3498,10 @@
                  localOp.setAuthFailureReason(message);
                  pwPolicyState.generateAccountStatusNotification(
                       AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
                          message);
                       AccountStatusNotificationType.PASSWORD_EXPIRED,
                       userEntry, message,
                       AccountStatusNotification.createProperties(pwPolicyState,
                             false, -1, null, null));
                  break bindProcessing;
                }
@@ -3494,8 +3515,10 @@
                localOp.setAuthFailureReason(message);
                pwPolicyState.generateAccountStatusNotification(
                     AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
                        message);
                     AccountStatusNotificationType.PASSWORD_EXPIRED, userEntry,
                     message,
                     AccountStatusNotification.createProperties(pwPolicyState,
                           false, -1, null, null));
                break bindProcessing;
              }
@@ -3766,8 +3789,10 @@
                        timeToExpiration);
                pwPolicyState.generateAccountStatusNotification(
                     AccountStatusNotificationType.PASSWORD_EXPIRING, bindDN,
                        message);
                     AccountStatusNotificationType.PASSWORD_EXPIRING, userEntry,
                     message,
                     AccountStatusNotification.createProperties(pwPolicyState,
                           false, numSeconds, null, null));
              }
              if (isGraceLogin)
@@ -3791,11 +3816,13 @@
                {
                  AccountStatusNotificationType notificationType;
                  boolean tempLocked;
                  int lockoutDuration = pwPolicyState.getSecondsUntilUnlock();
                  if (lockoutDuration > -1)
                  {
                    notificationType = AccountStatusNotificationType.
                                            ACCOUNT_TEMPORARILY_LOCKED;
                    tempLocked = true;
                    message = ERR_BIND_ACCOUNT_TEMPORARILY_LOCKED.get(
                            secondsToTimeString(lockoutDuration));
@@ -3804,13 +3831,15 @@
                  {
                    notificationType = AccountStatusNotificationType.
                                            ACCOUNT_PERMANENTLY_LOCKED;
                    tempLocked = false;
                    message = ERR_BIND_ACCOUNT_PERMANENTLY_LOCKED.get();
                  }
                  pwPolicyState.generateAccountStatusNotification(
                       notificationType, localOp.getUserEntryDN(),
                          message);
                       notificationType, userEntry, message,
                       AccountStatusNotification.createProperties(pwPolicyState,
                             tempLocked, -1, null, null));
                }
              }
            }
@@ -3990,8 +4019,10 @@
              localOp.setAuthFailureReason(message);
              pwPolicyState.generateAccountStatusNotification(
                   AccountStatusNotificationType.ACCOUNT_EXPIRED, bindDN,
                      message);
                   AccountStatusNotificationType.ACCOUNT_EXPIRED,
                   saslAuthUserEntry, message,
                   AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              break bindProcessing;
            }
@@ -4037,8 +4068,10 @@
              localOp.setAuthFailureReason(message);
              pwPolicyState.generateAccountStatusNotification(
                   AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED, bindDN,
                      message);
                   AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED,
                   saslAuthUserEntry, message,
                   AccountStatusNotification.createProperties(pwPolicyState,
                         false, -1, null, null));
              break bindProcessing;
            }
@@ -4060,8 +4093,10 @@
                localOp.setAuthFailureReason(message);
                pwPolicyState.generateAccountStatusNotification(
                     AccountStatusNotificationType.ACCOUNT_RESET_LOCKED, bindDN,
                        message);
                     AccountStatusNotificationType.ACCOUNT_RESET_LOCKED,
                     saslAuthUserEntry, message,
                     AccountStatusNotification.createProperties(pwPolicyState,
                           false, -1, null, null));
                break bindProcessing;
              }
@@ -4101,8 +4136,10 @@
                    localOp.setAuthFailureReason(message);
                    pwPolicyState.generateAccountStatusNotification(
                         AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
                            message);
                         AccountStatusNotificationType.PASSWORD_EXPIRED,
                         saslAuthUserEntry, message,
                         AccountStatusNotification.createProperties(
                              pwPolicyState, false, -1, null, null));
                    break bindProcessing;
                  }
@@ -4116,8 +4153,10 @@
                  localOp.setAuthFailureReason(message);
                  pwPolicyState.generateAccountStatusNotification(
                       AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
                          message);
                       AccountStatusNotificationType.PASSWORD_EXPIRED,
                       saslAuthUserEntry, message,
                       AccountStatusNotification.createProperties(pwPolicyState,
                             false, -1, null, null));
                  break bindProcessing;
                }
@@ -4169,8 +4208,10 @@
                        timeToExpiration);
                pwPolicyState.generateAccountStatusNotification(
                     AccountStatusNotificationType.PASSWORD_EXPIRING, bindDN,
                        message);
                     AccountStatusNotificationType.PASSWORD_EXPIRING,
                     saslAuthUserEntry, message,
                     AccountStatusNotification.createProperties(pwPolicyState,
                           false, numSeconds, null, null));
              }
              if (isGraceLogin)
@@ -4369,6 +4410,7 @@
                  if (pwPolicyState.lockedDueToFailures())
                  {
                    AccountStatusNotificationType notificationType;
                    boolean tempLocked;
                    Message message;
                    int lockoutDuration = pwPolicyState.getSecondsUntilUnlock();
@@ -4376,6 +4418,7 @@
                    {
                      notificationType = AccountStatusNotificationType.
                                              ACCOUNT_TEMPORARILY_LOCKED;
                      tempLocked = true;
                      message = ERR_BIND_ACCOUNT_TEMPORARILY_LOCKED.get(
                              secondsToTimeString(lockoutDuration));
                    }
@@ -4383,12 +4426,14 @@
                    {
                      notificationType = AccountStatusNotificationType.
                                              ACCOUNT_PERMANENTLY_LOCKED;
                      tempLocked = false;
                      message = ERR_BIND_ACCOUNT_PERMANENTLY_LOCKED.get();
                    }
                    pwPolicyState.generateAccountStatusNotification(
                         notificationType, localOp.getUserEntryDN(),
                            message);
                         notificationType, saslAuthUserEntry, message,
                         AccountStatusNotification.createProperties(
                              pwPolicyState, tempLocked, -1, null, null));
                  }
                }
              }
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ErrorLogAccountStatusNotificationHandlerTestCase.java
@@ -28,6 +28,9 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.testng.annotations.BeforeClass;
@@ -45,6 +48,10 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PasswordPolicy;
import org.opends.server.core.PasswordPolicyState;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationProperty;
import org.opends.server.types.AccountStatusNotificationType;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -52,6 +59,9 @@
import static org.testng.Assert.*;
import static org.opends.server.types.AccountStatusNotificationType.*;
import static org.opends.server.types.AccountStatusNotificationProperty.*;
/**
@@ -213,6 +223,9 @@
  /**
   * Tests the <CODE>handleStatusNotification</CODE> method.
   *
   * @param  notificationType  The account status notification type to be
   *                           tested.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "notificationTypes")
@@ -220,6 +233,19 @@
                   AccountStatusNotificationType notificationType)
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    TestCaseUtils.addEntry(
      "dn: uid=test.user,o=test",
      "objectClass: top",
      "objectClass: person",
      "objectClass: organizationalPerson",
      "objectClass: inetOrgPerson",
      "uid: test.user",
      "givenName: Test",
      "sn: User",
      "cn: Test User",
      "userPassword: password");
    String dnStr = "cn=Error Log Handler,cn=Account Status Notification " +
                        "Handlers,cn=config";
    DN handlerDN = DN.decode(dnStr);
@@ -227,9 +253,68 @@
         DirectoryServer.getAccountStatusNotificationHandler(handlerDN);
    assertNotNull(handler);
    DN userDN = DN.decode("uid=test.user,o=test");
    handler.handleStatusNotification(notificationType, userDN,
            Message.raw("Test Notification"));
    Entry userEntry =
               DirectoryServer.getEntry(DN.decode("uid=test.user,o=test"));
    PasswordPolicyState pwPolicyState =
         new PasswordPolicyState(userEntry, false, false);
    PasswordPolicy policy = pwPolicyState.getPolicy();
    HashMap<AccountStatusNotificationProperty,List<String>>
         notificationProperties =
              new HashMap<AccountStatusNotificationProperty,List<String>>();
    ArrayList<String> propList = new ArrayList<String>(1);
    propList.add(policy.getConfigEntryDN().toString());
    notificationProperties.put(PASSWORD_POLICY_DN, propList);
    if (notificationType == ACCOUNT_TEMPORARILY_LOCKED)
    {
      propList = new ArrayList<String>(1);
      propList.add("300");
      notificationProperties.put(SECONDS_UNTIL_UNLOCK, propList);
      propList = new ArrayList<String>(1);
      propList.add("5 minutes");
      notificationProperties.put(TIME_UNTIL_UNLOCK, propList);
      propList = new ArrayList<String>(1);
      propList.add(new Date(System.currentTimeMillis() + 300000L).toString());
      notificationProperties.put(ACCOUNT_UNLOCK_TIME, propList);
    }
    else if (notificationType == PASSWORD_EXPIRING)
    {
      propList = new ArrayList<String>(1);
      propList.add("86400");
      notificationProperties.put(SECONDS_UNTIL_EXPIRATION, propList);
      propList = new ArrayList<String>(1);
      propList.add("1 day");
      notificationProperties.put(TIME_UNTIL_EXPIRATION, propList);
      propList = new ArrayList<String>(1);
      propList.add(new Date(System.currentTimeMillis() + 86400000L).toString());
      notificationProperties.put(PASSWORD_EXPIRATION_TIME, propList);
    }
    else if ((notificationType == PASSWORD_CHANGED) ||
             (notificationType == PASSWORD_RESET))
    {
      propList = new ArrayList<String>(1);
      propList.add("oldpassword");
      notificationProperties.put(OLD_PASSWORD, propList);
      propList = new ArrayList<String>(1);
      propList.add("newpassword");
      notificationProperties.put(NEW_PASSWORD, propList);
    }
    AccountStatusNotification notification =
         new AccountStatusNotification(notificationType, userEntry,
                                       Message.raw("Test Modification"),
                                       notificationProperties);
    handler.handleStatusNotification(notification);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TestAccountStatusNotificationHandler.java
New file
@@ -0,0 +1,152 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
import java.util.concurrent.atomic.AtomicInteger;
import org.opends.server.admin.std.server.
       AccountStatusNotificationHandlerCfg;
import org.opends.server.api.AccountStatusNotificationHandler;
import org.opends.server.types.AccountStatusNotification;
import static org.testng.Assert.*;
import static org.opends.server.types.AccountStatusNotificationProperty.*;
/**
 * This class implements a simple account status notification handler that may
 * be used to ensure that all notifications are generated properly.
 */
public class TestAccountStatusNotificationHandler
extends AccountStatusNotificationHandler<AccountStatusNotificationHandlerCfg>
{
  // The number of notifications that this handler has processed.
  private static AtomicInteger notificationsProcessed = new AtomicInteger(0);
  /**
   * Creates a new instance of this test account status notification handler.
   */
  public TestAccountStatusNotificationHandler()
  {
    // No implementation is required.
  }
  /**
   * {@inheritDoc}
   */
  public void initializeStatusNotificationHandler(
                   AccountStatusNotificationHandlerCfg configuration)
  {
    // No implementation is required.
  }
  /**
   * {@inheritDoc}
   */
  public void handleStatusNotification(AccountStatusNotification notification)
  {
    notificationsProcessed.incrementAndGet();
    assertNotNull(notification);
    assertNotNull(notification.getNotificationType());
    assertNotNull(notification.getUserDN());
    assertNotNull(notification.getUserEntry());
    assertNotNull(notification.getMessage());
    assertNotNull(notification.getNotificationProperties());
    assertNotNull(
         notification.getNotificationProperties().get(PASSWORD_POLICY_DN));
    switch (notification.getNotificationType())
    {
      case ACCOUNT_TEMPORARILY_LOCKED:
        assertNotNull(
             notification.getNotificationProperties().get(ACCOUNT_UNLOCK_TIME));
        assertNotNull(
             notification.getNotificationProperties().get(
                  SECONDS_UNTIL_UNLOCK));
        assertNotNull(
             notification.getNotificationProperties().get(TIME_UNTIL_UNLOCK));
        break;
      case PASSWORD_EXPIRING:
        assertNotNull(
             notification.getNotificationProperties().get(
                  PASSWORD_EXPIRATION_TIME));
        assertNotNull(
             notification.getNotificationProperties().get(
                  SECONDS_UNTIL_EXPIRATION));
        assertNotNull(
             notification.getNotificationProperties().get(
                  TIME_UNTIL_EXPIRATION));
        break;
      case PASSWORD_CHANGED:
      case PASSWORD_RESET:
        // Note that the old password may not always be available, so we
        // can't check for it.
        assertNotNull(
             notification.getNotificationProperties().get(NEW_PASSWORD));
        break;
    }
  }
  /**
   * Retrieves the number of account status notifications that this handler has
   * processed.
   *
   * @return  The number of account status notifications that this handler has
   *          processed.
   */
  public static int getNotificationsProcessed()
  {
    return notificationsProcessed.get();
  }
  /**
   * Resets the counter used to keep track fo the number of account status
   * notfications that this handler has processed.
   */
  public static void resetCount()
  {
    notificationsProcessed.set(0);
  }
}