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.extensions;
022    
023    
024    
025    import java.util.ArrayList;
026    
027    import com.unboundid.asn1.ASN1Element;
028    import com.unboundid.asn1.ASN1OctetString;
029    import com.unboundid.asn1.ASN1Sequence;
030    import com.unboundid.ldap.sdk.Control;
031    import com.unboundid.ldap.sdk.ExtendedResult;
032    import com.unboundid.ldap.sdk.LDAPException;
033    import com.unboundid.ldap.sdk.ResultCode;
034    import com.unboundid.util.Debug;
035    import com.unboundid.util.NotMutable;
036    import com.unboundid.util.StaticUtils;
037    import com.unboundid.util.ThreadSafety;
038    import com.unboundid.util.ThreadSafetyLevel;
039    import com.unboundid.util.Validator;
040    
041    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
042    
043    
044    
045    /**
046     * <BLOCKQUOTE>
047     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
048     *   LDAP SDK for Java.  It is not available for use in applications that
049     *   include only the Standard Edition of the LDAP SDK, and is not supported for
050     *   use in conjunction with non-UnboundID products.
051     * </BLOCKQUOTE>
052     * This class provides an implementation of an extended result that may be used
053     * to provide information about the result of processing for a deliver password
054     * reset token extended request.  If the token was delivered successfully, then
055     * this result will include information about the mechanism through which the
056     * token was delivered.
057     * <BR><BR>
058     * If the request was processed successfully, then the extended result will have
059     * an OID of 1.3.6.1.4.1.30221.2.6.46 and a value with the following encoding:
060     * <BR><BR>
061     * <PRE>
062     *   DeliverPasswordResetTokenResult ::= SEQUENCE {
063     *        deliveryMechanism     OCTET STRING,
064     *        recipientID           [0] OCTET STRING OPTIONAL,
065     *        message               [1] OCTET STRING OPTIONAL,
066     *        ... }
067     * </PRE>
068     *
069     * @see  DeliverPasswordResetTokenExtendedRequest
070     */
071    @NotMutable()
072    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
073    public final class DeliverPasswordResetTokenExtendedResult
074           extends ExtendedResult
075    {
076      /**
077       * The OID (1.3.6.1.4.1.30221.2.6.46) for the deliver password reset token
078       * extended result.
079       */
080      public static final String DELIVER_PW_RESET_TOKEN_RESULT_OID =
081           "1.3.6.1.4.1.30221.2.6.46";
082    
083    
084    
085      /**
086       * The BER type for the recipient ID element of the value sequence.
087       */
088      private static final byte RECIPIENT_ID_BER_TYPE = (byte) 0x80;
089    
090    
091    
092      /**
093       * The BER type for the message element of the value sequence.
094       */
095      private static final byte DELIVERY_MESSAGE_BER_TYPE = (byte) 0x81;
096    
097    
098    
099      /**
100       * The serial version UID for this serializable class.
101       */
102      private static final long serialVersionUID = 576599499447071902L;
103    
104    
105    
106      // The name of the mechanism by which the password reset token was delivered.
107      private final String deliveryMechanism;
108    
109      // An message providing additional information about the delivery of the
110      // password reset token.
111      private final String deliveryMessage;
112    
113      // An identifier for the recipient of the password reset token.
114      private final String recipientID;
115    
116    
117    
118      /**
119       * Creates a new deliver password reset token extended result with the
120       * provided information.
121       *
122       * @param  messageID          The message ID for the LDAP message that is
123       *                            associated with this LDAP result.
124       * @param  resultCode         The result code from the response.  It must not
125       *                            be {@code null}.
126       * @param  diagnosticMessage  The diagnostic message from the response, if
127       *                            available.
128       * @param  matchedDN          The matched DN from the response, if available.
129       * @param  referralURLs       The set of referral URLs from the response, if
130       *                            available.
131       * @param  deliveryMechanism  The name of the mechanism by which the password
132       *                            reset token was delivered, if available.  This
133       *                            should be non-{@code null} for a success result.
134       * @param  recipientID        An identifier for the user to whom the password
135       *                            reset token was delivered.  It may be
136       *                            {@code null} if no token was delivered or there
137       *                            is no appropriate identifier, but if a value is
138       *                            provided then it should appropriate for the
139       *                            delivery mechanism (e.g., the user's e-mail
140       *                            address if delivered via e-mail, a phone number
141       *                            if delivered via SMS or voice call, etc.).
142       * @param  deliveryMessage    An optional message providing additional
143       *                            information about the password reset token
144       *                            delivery, if available.  If this is
145       *                            non-{@code null}, then the delivery mechanism
146       *                            must also be non-null.
147       * @param  responseControls   The set of controls for the response, if
148       *                            available.
149       */
150      public DeliverPasswordResetTokenExtendedResult(final int messageID,
151                  final ResultCode resultCode, final String diagnosticMessage,
152                  final String matchedDN, final String[] referralURLs,
153                  final String deliveryMechanism, final String recipientID,
154                  final String deliveryMessage, final Control... responseControls)
155      {
156        super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
157             ((deliveryMechanism == null)
158                  ? null : DELIVER_PW_RESET_TOKEN_RESULT_OID),
159             encodeValue(deliveryMechanism, recipientID, deliveryMessage),
160             responseControls);
161    
162        this.deliveryMechanism = deliveryMechanism;
163        this.recipientID       = recipientID;
164        this.deliveryMessage   = deliveryMessage;
165      }
166    
167    
168    
169      /**
170       * Creates a new deliver password reset token result from the provided generic
171       * extended result.
172       *
173       * @param  result  The generic extended result to be parsed as a deliver
174       *                 password reset token result.
175       *
176       * @throws LDAPException  If the provided extended result cannot be parsed as
177       *                         a deliver password reset token result.
178       */
179      public DeliverPasswordResetTokenExtendedResult(final ExtendedResult result)
180           throws LDAPException
181      {
182        super(result);
183    
184        final ASN1OctetString value = result.getValue();
185        if (value == null)
186        {
187          deliveryMechanism = null;
188          recipientID       = null;
189          deliveryMessage   = null;
190          return;
191        }
192    
193        try
194        {
195          final ASN1Element[] elements =
196               ASN1Sequence.decodeAsSequence(value.getValue()).elements();
197          deliveryMechanism =
198               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
199    
200          String id = null;
201          String msg = null;
202          for (int i=1; i < elements.length; i++)
203          {
204            switch (elements[i].getType())
205            {
206              case RECIPIENT_ID_BER_TYPE:
207                id = ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
208                break;
209    
210              case DELIVERY_MESSAGE_BER_TYPE:
211                msg = ASN1OctetString.decodeAsOctetString(
212                     elements[i]).stringValue();
213                break;
214    
215              default:
216                throw new LDAPException(ResultCode.DECODING_ERROR,
217                     ERR_DELIVER_PW_RESET_TOKEN_RESULT_UNEXPECTED_TYPE.get(
218                          StaticUtils.toHex(elements[i].getType())));
219            }
220          }
221    
222          recipientID = id;
223          deliveryMessage = msg;
224        }
225        catch (final LDAPException le)
226        {
227          Debug.debugException(le);
228          throw le;
229        }
230        catch (final Exception e)
231        {
232          Debug.debugException(e);
233          throw new LDAPException(ResultCode.DECODING_ERROR,
234               ERR_DELIVER_PW_RESET_TOKEN_RESULT_ERROR_DECODING_VALUE.get(
235                    StaticUtils.getExceptionMessage(e)),
236               e);
237        }
238      }
239    
240    
241    
242      /**
243       * Encodes the provided information into an ASN.1 octet string suitable for
244       * use as the value of this extended result.
245       *
246       * @param  deliveryMechanism  The name of the mechanism by which the password
247       *                            reset token was delivered, if available.  This
248       *                            should be non-{@code null} for a success result.
249       * @param  recipientID        An identifier for the user to whom the password
250       *                            reset token was delivered.  It may be
251       *                            {@code null} if no token was delivered or there
252       *                            is no appropriate identifier, but if a value is
253       *                            provided then it should appropriate for the
254       *                            delivery mechanism (e.g., the user's e-mail
255       *                            address if delivered via e-mail, a phone number
256       *                            if delivered via SMS or voice call, etc.).
257       * @param  deliveryMessage    An optional message providing additional
258       *                            information about the password reset token
259       *                            delivery, if available.  If this is
260       *                            non-{@code null}, then the delivery mechanism
261       *                            must also be non-null.
262       *
263       * @return  An ASN.1 octet string containing the encoded value, or
264       *          {@code null} if the extended result should not have a value.
265       */
266      private static ASN1OctetString encodeValue(final String deliveryMechanism,
267                                                 final String recipientID,
268                                                 final String deliveryMessage)
269      {
270        if (deliveryMechanism == null)
271        {
272          Validator.ensureTrue((recipientID == null),
273               "The delivery mechanism must be non-null if the recipient ID " +
274                    "is non-null.");
275          Validator.ensureTrue((deliveryMessage == null),
276               "The delivery mechanism must be non-null if the delivery message " +
277                    "is non-null.");
278          return null;
279        }
280    
281        final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(3);
282        elements.add(new ASN1OctetString(deliveryMechanism));
283    
284        if (recipientID != null)
285        {
286          elements.add(new ASN1OctetString(RECIPIENT_ID_BER_TYPE, recipientID));
287        }
288    
289        if (deliveryMessage != null)
290        {
291          elements.add(new ASN1OctetString(DELIVERY_MESSAGE_BER_TYPE,
292               deliveryMessage));
293        }
294    
295        return new ASN1OctetString(new ASN1Sequence(elements).encode());
296      }
297    
298    
299    
300      /**
301       * Retrieves the name of the mechanism by which the password reset token was
302       * delivered to the user, if available.
303       *
304       * @return  The name of the mechanism by which the password reset token was
305       *          delivered to the user, or {@code null} if this is not available.
306       */
307      public String getDeliveryMechanism()
308      {
309        return deliveryMechanism;
310      }
311    
312    
313    
314      /**
315       * Retrieves an identifier for the user to whom the password reset token was
316       * delivered, if available.  If a recipient ID is provided, then it should be
317       * in a form appropriate to the delivery mechanism (e.g., an e-mail address
318       * if the token was delivered by e-mail, a phone number if it was delivered
319       * by SMS or a voice call, etc.).
320       *
321       * @return  An identifier for the user to whom the password reset token was
322       *          delivered, or {@code null} if this is not available.
323       */
324      public String getRecipientID()
325      {
326        return recipientID;
327      }
328    
329    
330    
331      /**
332       * Retrieves a message providing additional information about the password
333       * reset token delivery, if available.
334       *
335       * @return  A message providing additional information about the password
336       *          reset token delivery, or {@code null} if this is not available.
337       */
338      public String getDeliveryMessage()
339      {
340        return deliveryMessage;
341      }
342    
343    
344    
345      /**
346       * {@inheritDoc}
347       */
348      @Override()
349      public String getExtendedResultName()
350      {
351        return INFO_EXTENDED_RESULT_NAME_DELIVER_PW_RESET_TOKEN.get();
352      }
353    
354    
355    
356      /**
357       * Appends a string representation of this extended result to the provided
358       * buffer.
359       *
360       * @param  buffer  The buffer to which a string representation of this
361       *                 extended result will be appended.
362       */
363      @Override()
364      public void toString(final StringBuilder buffer)
365      {
366        buffer.append("DeliverPasswordResetTokenExtendedResult(resultCode=");
367        buffer.append(getResultCode());
368    
369        final int messageID = getMessageID();
370        if (messageID >= 0)
371        {
372          buffer.append(", messageID=");
373          buffer.append(messageID);
374        }
375    
376        if (deliveryMechanism != null)
377        {
378          buffer.append(", deliveryMechanism='");
379          buffer.append(deliveryMechanism);
380          buffer.append('\'');
381        }
382    
383        if (recipientID != null)
384        {
385          buffer.append(", recipientID='");
386          buffer.append(recipientID);
387          buffer.append('\'');
388        }
389    
390        if (deliveryMessage != null)
391        {
392          buffer.append(", deliveryMessage='");
393          buffer.append(deliveryMessage);
394          buffer.append('\'');
395        }
396    
397        final String diagnosticMessage = getDiagnosticMessage();
398        if (diagnosticMessage != null)
399        {
400          buffer.append(", diagnosticMessage='");
401          buffer.append(diagnosticMessage);
402          buffer.append('\'');
403        }
404    
405        final String matchedDN = getMatchedDN();
406        if (matchedDN != null)
407        {
408          buffer.append(", matchedDN='");
409          buffer.append(matchedDN);
410          buffer.append('\'');
411        }
412    
413        final String[] referralURLs = getReferralURLs();
414        if (referralURLs.length > 0)
415        {
416          buffer.append(", referralURLs={");
417          for (int i=0; i < referralURLs.length; i++)
418          {
419            if (i > 0)
420            {
421              buffer.append(", ");
422            }
423    
424            buffer.append('\'');
425            buffer.append(referralURLs[i]);
426            buffer.append('\'');
427          }
428          buffer.append('}');
429        }
430    
431        final Control[] responseControls = getResponseControls();
432        if (responseControls.length > 0)
433        {
434          buffer.append(", responseControls={");
435          for (int i=0; i < responseControls.length; i++)
436          {
437            if (i > 0)
438            {
439              buffer.append(", ");
440            }
441    
442            buffer.append(responseControls[i]);
443          }
444          buffer.append('}');
445        }
446    
447        buffer.append(')');
448      }
449    }