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}