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