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    }