001 /* 002 * Copyright 2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2015 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021 package com.unboundid.ldap.sdk.unboundidds.controls; 022 023 024 025 import java.io.Serializable; 026 import java.util.ArrayList; 027 028 import com.unboundid.asn1.ASN1Boolean; 029 import com.unboundid.asn1.ASN1Element; 030 import com.unboundid.asn1.ASN1OctetString; 031 import com.unboundid.asn1.ASN1Sequence; 032 import com.unboundid.ldap.sdk.LDAPException; 033 import com.unboundid.ldap.sdk.ResultCode; 034 import com.unboundid.ldap.sdk.unboundidds.extensions.PasswordQualityRequirement; 035 import com.unboundid.util.Debug; 036 import com.unboundid.util.NotMutable; 037 import com.unboundid.util.StaticUtils; 038 import com.unboundid.util.ThreadSafety; 039 import com.unboundid.util.ThreadSafetyLevel; 040 import com.unboundid.util.Validator; 041 042 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 043 044 045 046 /** 047 * <BLOCKQUOTE> 048 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 049 * LDAP SDK for Java. It is not available for use in applications that 050 * include only the Standard Edition of the LDAP SDK, and is not supported for 051 * use in conjunction with non-UnboundID products. 052 * </BLOCKQUOTE> 053 * This class provides a data structure that holds information about the result 054 * of attempting validation with a proposed password against a password quality 055 * requirement. 056 * <BR><BR> 057 * If it appears in an LDAP protocol element (e.g., in a password validation 058 * details response control), then the password quality validation result object 059 * should have the following ASN.1 encoding: 060 * <PRE> 061 * PasswordQualityRequirementValidationResult ::= SEQUENCE { 062 * passwordRequirement PasswordQualityRequirement, 063 * requirementSatisfied BOOLEAN, 064 * additionalInfo [0] OCTET STRING OPTIONAL } 065 * </PRE> 066 */ 067 @NotMutable() 068 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 069 public final class PasswordQualityRequirementValidationResult 070 implements Serializable 071 { 072 /** 073 * The BER type for the additional info element of the value sequence. 074 */ 075 private static final byte TYPE_ADDITIONAL_INFO = (byte) 0x80; 076 077 078 079 /** 080 * The serial version UID for this serializable class. 081 */ 082 private static final long serialVersionUID = -8048878239770726375L; 083 084 085 086 // Indicates whether the proposed password satisfied the constraints of the 087 // associated password quality requirement. 088 private final boolean requirementSatisfied; 089 090 // The password quality requirement to which this validation result applies. 091 private final PasswordQualityRequirement passwordRequirement; 092 093 // An optional message with additional information about the result of the 094 // validation for the proposed password with respect to the associated 095 // password quality requirement. 096 private final String additionalInfo; 097 098 099 100 /** 101 * Creates a new password quality requirement validation result object with 102 * the provided information. 103 * 104 * @param passwordRequirement The password quality requirement to which 105 * this validation result applies. This must 106 * not be {@code null}. 107 * @param requirementSatisfied Indicates whether the proposed password 108 * satisfied the constraints of the associated 109 * password quality requirement. 110 * @param additionalInfo An optional message with additional 111 * information about the result of the 112 * validation for the proposed password with 113 * respect to the associated password quality 114 * requirement. 115 */ 116 public PasswordQualityRequirementValidationResult( 117 final PasswordQualityRequirement passwordRequirement, 118 final boolean requirementSatisfied, final String additionalInfo) 119 { 120 Validator.ensureNotNull(passwordRequirement); 121 122 this.passwordRequirement = passwordRequirement; 123 this.requirementSatisfied = requirementSatisfied; 124 this.additionalInfo = additionalInfo; 125 } 126 127 128 129 /** 130 * Retrieves the password quality requirement to which this validation result 131 * applies. 132 * 133 * @return The password quality requirement to which this validation result 134 * applies. 135 */ 136 public PasswordQualityRequirement getPasswordRequirement() 137 { 138 return passwordRequirement; 139 } 140 141 142 143 /** 144 * Indicates whether the proposed password satisfied the constraints of the 145 * associated password quality requirement. 146 * 147 * @return {@code true} if the proposed password satisfied the constraints of 148 * the associated password quality requirement, or {@code false} if 149 * not. 150 */ 151 public boolean requirementSatisfied() 152 { 153 return requirementSatisfied; 154 } 155 156 157 158 /** 159 * Retrieves a message with additional information about the result of the 160 * validation of the proposed password with respect to the associated 161 * password quality requirement. 162 * 163 * @return A message with additional information about the result of the 164 * validation, or {@code null} if no additional information is 165 * available. 166 */ 167 public String getAdditionalInfo() 168 { 169 return additionalInfo; 170 } 171 172 173 174 /** 175 * Encodes this password quality requirement validation result object to an 176 * ASN.1 element. 177 * 178 * @return The ASN.1 element that provides an encoded representation of this 179 * object. 180 */ 181 public ASN1Element encode() 182 { 183 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(3); 184 elements.add(passwordRequirement.encode()); 185 elements.add(new ASN1Boolean(requirementSatisfied)); 186 187 if (additionalInfo != null) 188 { 189 elements.add(new ASN1OctetString(TYPE_ADDITIONAL_INFO, additionalInfo)); 190 } 191 192 return new ASN1Sequence(elements); 193 } 194 195 196 197 /** 198 * Decodes the provided ASN.1 element as a password quality requirement 199 * validation result. 200 * 201 * @param element The ASN.1 element to be decoded as a password quality 202 * requirement validation result. 203 * 204 * @return The ASN.1 element containing the encoded password quality 205 * requirement validation result. 206 * 207 * @throws LDAPException If a problem is encountered while attempting to 208 * decode the provided ASN.1 element. 209 */ 210 public static PasswordQualityRequirementValidationResult decode( 211 final ASN1Element element) 212 throws LDAPException 213 { 214 try 215 { 216 final ASN1Element[] elements = 217 ASN1Sequence.decodeAsSequence(element).elements(); 218 final PasswordQualityRequirement passwordRequirement = 219 PasswordQualityRequirement.decode(elements[0]); 220 final boolean requirementSatisfied = 221 ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue(); 222 223 String additionalInfo = null; 224 for (int i=2; i < elements.length; i++) 225 { 226 switch (elements[i].getType()) 227 { 228 case TYPE_ADDITIONAL_INFO: 229 additionalInfo = 230 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 231 break; 232 233 default: 234 throw new LDAPException(ResultCode.DECODING_ERROR, 235 ERR_PW_REQ_VALIDATION_RESULT_INVALID_ELEMENT_TYPE.get( 236 StaticUtils.toHex(elements[i].getType()))); 237 } 238 } 239 240 return new PasswordQualityRequirementValidationResult(passwordRequirement, 241 requirementSatisfied, additionalInfo); 242 } 243 catch (final LDAPException le) 244 { 245 Debug.debugException(le); 246 throw le; 247 } 248 catch (final Exception e) 249 { 250 Debug.debugException(e); 251 throw new LDAPException(ResultCode.DECODING_ERROR, 252 ERR_PW_REQ_VALIDATION_RESULT_CANNOT_DECODE.get( 253 StaticUtils.getExceptionMessage(e)), 254 e); 255 } 256 } 257 258 259 260 /** 261 * Retrieves a string representation of this password quality requirement 262 * validation result. 263 * 264 * @return A string representation of this password quality requirement 265 * validation result. 266 */ 267 @Override() 268 public String toString() 269 { 270 final StringBuilder buffer = new StringBuilder(); 271 toString(buffer); 272 return buffer.toString(); 273 } 274 275 276 277 /** 278 * Appends a string representation of this password quality requirement 279 * validation result to the provided buffer. 280 * 281 * @param buffer The buffer to which the information should be appended. 282 */ 283 public void toString(final StringBuilder buffer) 284 { 285 buffer.append("PasswordQualityRequirementValidationResult(requirement="); 286 passwordRequirement.toString(buffer); 287 buffer.append(", requirementSatisfied="); 288 buffer.append(requirementSatisfied); 289 290 if (additionalInfo != null) 291 { 292 buffer.append(", additionalInfo='"); 293 buffer.append(additionalInfo); 294 buffer.append('\''); 295 } 296 297 buffer.append(')'); 298 } 299 }