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 import java.util.Collections;
027 import java.util.Iterator;
028 import java.util.List;
029
030 import com.unboundid.asn1.ASN1Element;
031 import com.unboundid.asn1.ASN1OctetString;
032 import com.unboundid.asn1.ASN1Sequence;
033 import com.unboundid.ldap.sdk.Control;
034 import com.unboundid.ldap.sdk.ExtendedRequest;
035 import com.unboundid.ldap.sdk.ExtendedResult;
036 import com.unboundid.ldap.sdk.LDAPConnection;
037 import com.unboundid.ldap.sdk.LDAPException;
038 import com.unboundid.ldap.sdk.ResultCode;
039 import com.unboundid.util.Debug;
040 import com.unboundid.util.NotMutable;
041 import com.unboundid.util.ObjectPair;
042 import com.unboundid.util.StaticUtils;
043 import com.unboundid.util.ThreadSafety;
044 import com.unboundid.util.ThreadSafetyLevel;
045 import com.unboundid.util.Validator;
046
047 import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
048
049
050
051 /**
052 * <BLOCKQUOTE>
053 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
054 * LDAP SDK for Java. It is not available for use in applications that
055 * include only the Standard Edition of the LDAP SDK, and is not supported for
056 * use in conjunction with non-UnboundID products.
057 * </BLOCKQUOTE>
058 * This class provides an implementation of an extended request that can be used
059 * to trigger the delivery of a temporary one-time password reset token to a
060 * specified user. This token can be provided to the password modify extended
061 * request in lieu of the current password for the purpose of performing a self
062 * change and setting a new password. This token cannot be used to authenticate
063 * to the server in any other way, and it can only be used once. The token will
064 * expire after a short period of time, and any attempt to use it after its
065 * expiration will fail. In addition, because this token is only intended for
066 * use in the event that the current password cannot be used (e.g., because it
067 * has been forgotten or the account is locked), a successful bind with the
068 * current password will cause the server to invalidate any password reset token
069 * for that user.
070 * <BR><BR>
071 * The server will use the same mechanisms for delivering password reset tokens
072 * as it uses for delivering one-time passwords via the
073 * {@link DeliverOneTimePasswordExtendedRequest}. See the
074 * ds-supported-otp-delivery-mechanism attribute in the root DSE for a list of
075 * the one-time password delivery mechanisms that are configured for use in the
076 * server.
077 * <BR><BR>
078 * This extended request is expected to be used to help applications provide a
079 * secure, automated password reset feature. In the event that a user has
080 * forgotten his/her password, has allowed the password to expire, or has
081 * allowed the account to become locked, the application can collect a
082 * sufficient set of information to identify the user and request that the
083 * server generate and deliver the password reset token to the end user.
084 * <BR><BR>
085 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.45. It must have
086 * a value with the following encoding:
087 * <PRE>
088 * DeliverPasswordResetTokenRequestValue ::= SEQUENCE {
089 * userDN LDAPDN,
090 * messageSubject [0] OCTET STRING OPTIONAL,
091 * fullTextBeforeToken [1] OCTET STRING OPTIONAL,
092 * fullTextAfterToken [2] OCTET STRING OPTIONAL,
093 * compactTextBeforeToken [3] OCTET STRING OPTIONAL,
094 * compactTextAfterToken [4] OCTET STRING OPTIONAL,
095 * preferredDeliveryMechanism [5] SEQUENCE OF SEQUENCE {
096 * mechanismName OCTET STRING,
097 * recipientID OCTET STRING OPTIONAL },
098 * ... }
099 * </PRE>
100 *
101 * @see DeliverPasswordResetTokenExtendedResult
102 */
103 @NotMutable()
104 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
105 public final class DeliverPasswordResetTokenExtendedRequest
106 extends ExtendedRequest
107 {
108 /**
109 * The OID (1.3.6.1.4.1.30221.2.6.45) for the deliver password reset token
110 * extended request.
111 */
112 public static final String DELIVER_PW_RESET_TOKEN_REQUEST_OID =
113 "1.3.6.1.4.1.30221.2.6.45";
114
115
116
117 /**
118 * The BER type for the "message subject" element of the value sequence.
119 */
120 private static final byte MESSAGE_SUBJECT_BER_TYPE = (byte) 0x80;
121
122
123
124 /**
125 * The BER type for the "full text before token" element of the value
126 * sequence.
127 */
128 private static final byte FULL_TEXT_BEFORE_TOKEN_BER_TYPE = (byte) 0x81;
129
130
131
132 /**
133 * The BER type for the "full text after token" element of the value
134 * sequence.
135 */
136 private static final byte FULL_TEXT_AFTER_TOKEN_BER_TYPE = (byte) 0x82;
137
138
139
140 /**
141 * The BER type for the "compact text before token" element of the value
142 * sequence.
143 */
144 private static final byte COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE = (byte) 0x83;
145
146
147
148 /**
149 * The BER type for the "compact text after token" element of the value
150 * sequence.
151 */
152 private static final byte COMPACT_TEXT_AFTER_TOKEN_BER_TYPE = (byte) 0x84;
153
154
155
156 /**
157 * The BER type for the "preferred delivery mechanism" element of the value
158 * sequence.
159 */
160 private static final byte PREFERRED_DELIVERY_MECHANISM_BER_TYPE = (byte) 0xA5;
161
162
163
164 /**
165 * The serial version UID for this serializable class.
166 */
167 private static final long serialVersionUID = 7608072810737347230L;
168
169
170
171 // An ordered list of the preferred delivery mechanisms for the token,
172 // paired with an optional recipient ID for each mechanism.
173 private final List<ObjectPair<String, String>> preferredDeliveryMechanisms;
174
175 // The text to include after the token in a compact message.
176 private final String compactTextAfterToken;
177
178 // The text to include before the token in a compact message.
179 private final String compactTextBeforeToken;
180
181 // The text to include after the token in a message without size constraints.
182 private final String fullTextAfterToken;
183
184 // The text to include before the token in a message without size constraints.
185 private final String fullTextBeforeToken;
186
187 // The text to use as the message subject.
188 private final String messageSubject;
189
190 // The DN of the user to whom the password reset token should be delivered.
191 private final String userDN;
192
193
194
195 /**
196 * Creates a new deliver password reset token extended request with the
197 * provided information.
198 *
199 * @param userDN The DN of the user to whom the
200 * password reset token should be
201 * generated.
202 * @param preferredDeliveryMechanisms An optional ordered list of preferred
203 * delivery mechanisms that should be
204 * used to deliver the token to the user.
205 * It may be {@code null} or empty to
206 * allow the server to select an
207 * appropriate delivery mechanism. If it
208 * is non-{@code null} and non-empty,
209 * then only the listed mechanisms will
210 * be considered for use, even if the
211 * server supports alternate mechanisms
212 * not included in this list.
213 */
214 public DeliverPasswordResetTokenExtendedRequest(final String userDN,
215 final String... preferredDeliveryMechanisms)
216 {
217 this(userDN, preferredMechanismsToList(preferredDeliveryMechanisms));
218 }
219
220
221
222 /**
223 * Creates a new deliver password reset token extended request with the
224 * provided information.
225 *
226 * @param userDN The DN of the user to whom the
227 * password reset token should be
228 * generated.
229 * @param preferredDeliveryMechanisms An optional ordered list of preferred
230 * delivery mechanisms that should be
231 * used to deliver the token to the user.
232 * It may be {@code null} or empty to
233 * allow the server to select an
234 * appropriate delivery mechanism. If it
235 * is non-{@code null} and non-empty,
236 * then only the listed mechanisms will
237 * be considered for use, even if the
238 * server supports alternate mechanisms
239 * not included in this list. Each
240 * {@code ObjectPair} item must have
241 * a non-{@code null} value for the first
242 * element, which is the name of the
243 * target delivery mechanism. It may
244 * optionally have a non-{@code null}
245 * value for the second element, which is
246 * a recipient ID to use for that
247 * mechanism (e.g., the target mobile
248 * phone number for SMS delivery, an
249 * email address for email delivery,
250 * etc.). If no recipient ID is provided
251 * for a mechanism, then the server will
252 * attempt to select a value for the
253 * user.
254 * @param controls An optional set of controls to include
255 * in the request. It may be
256 * {@code null} or empty if no controls
257 * should be included in the request.
258 */
259 public DeliverPasswordResetTokenExtendedRequest(final String userDN,
260 final List<ObjectPair<String,String>> preferredDeliveryMechanisms,
261 final Control... controls)
262 {
263 this(userDN, null, null, null, null, null, preferredDeliveryMechanisms,
264 controls);
265 }
266
267
268
269 /**
270 * Creates a new deliver password reset token extended request with the
271 * provided information.
272 *
273 * @param userDN The DN of the user to whom the
274 * password reset token should be
275 * generated.
276 * @param messageSubject The text (if any) that should be used
277 * as the message subject if the delivery
278 * mechanism accepts a subject. This may
279 * be {@code null} if no subject is
280 * required or a subject should be
281 * automatically generated.
282 * @param fullTextBeforeToken The text (if any) that should appear
283 * before the generated password reset
284 * token in the message delivered to the
285 * user via a delivery mechanism that
286 * does not impose significant
287 * constraints on message size. This may
288 * be {@code null} if no text is required
289 * before the token.
290 * @param fullTextAfterToken The text (if any) that should appear
291 * after the generated password reset
292 * token in the message delivered to the
293 * user via a delivery mechanism that
294 * does not impose significant
295 * constraints on message size. This may
296 * be {@code null} if no text is required
297 * after the token.
298 * @param compactTextBeforeToken The text (if any) that should appear
299 * before the generated password reset
300 * token in the message delivered to the
301 * user via a delivery mechanism that
302 * imposes significant constraints on
303 * message size. This may be
304 * {@code null} if no text is required
305 * before the token.
306 * @param compactTextAfterToken The text (if any) that should appear
307 * after the generated password reset
308 * token in the message delivered to the
309 * user via a delivery mechanism that
310 * imposes significant constraints on
311 * message size. This may be
312 * {@code null} if no text is required
313 * after the token.
314 * @param preferredDeliveryMechanisms An optional ordered list of preferred
315 * delivery mechanisms that should be
316 * used to deliver the token to the user.
317 * It may be {@code null} or empty to
318 * allow the server to select an
319 * appropriate delivery mechanism. If it
320 * is non-{@code null} and non-empty,
321 * then only the listed mechanisms will
322 * be considered for use, even if the
323 * server supports alternate mechanisms
324 * not included in this list. Each
325 * {@code ObjectPair} item must have
326 * a non-{@code null} value for the first
327 * element, which is the name of the
328 * target delivery mechanism. It may
329 * optionally have a non-{@code null}
330 * value for the second element, which is
331 * a recipient ID to use for that
332 * mechanism (e.g., the target mobile
333 * phone number for SMS delivery, an
334 * email address for email delivery,
335 * etc.). If no recipient ID is provided
336 * for a mechanism, then the server will
337 * attempt to select a value for the
338 * user.
339 * @param controls An optional set of controls to include
340 * in the request. It may be
341 * {@code null} or empty if no controls
342 * should be included in the request.
343 */
344 public DeliverPasswordResetTokenExtendedRequest(final String userDN,
345 final String messageSubject, final String fullTextBeforeToken,
346 final String fullTextAfterToken,
347 final String compactTextBeforeToken,
348 final String compactTextAfterToken,
349 final List<ObjectPair<String,String>> preferredDeliveryMechanisms,
350 final Control... controls)
351 {
352 super(DELIVER_PW_RESET_TOKEN_REQUEST_OID,
353 encodeValue(userDN, messageSubject, fullTextBeforeToken,
354 fullTextAfterToken, compactTextBeforeToken, compactTextAfterToken,
355 preferredDeliveryMechanisms), controls);
356
357 this.userDN = userDN;
358 this.messageSubject = messageSubject;
359 this.fullTextBeforeToken = fullTextBeforeToken;
360 this.fullTextAfterToken = fullTextAfterToken;
361 this.compactTextBeforeToken = compactTextBeforeToken;
362 this.compactTextAfterToken = compactTextAfterToken;
363
364 if (preferredDeliveryMechanisms == null)
365 {
366 this.preferredDeliveryMechanisms = Collections.emptyList();
367 }
368 else
369 {
370 this.preferredDeliveryMechanisms = Collections.unmodifiableList(
371 new ArrayList<ObjectPair<String,String>>(
372 preferredDeliveryMechanisms));
373 }
374 }
375
376
377
378 /**
379 * Creates a new deliver password reset token extended request that is decoded
380 * from the provided extended request.
381 *
382 * @param request The generic extended request to decode as a deliver
383 * password reset token request. It must not be
384 * {@code null}.
385 *
386 * @throws LDAPException If an unexpected problem occurs.
387 */
388 public DeliverPasswordResetTokenExtendedRequest(final ExtendedRequest request)
389 throws LDAPException
390 {
391 super(request);
392
393 final ASN1OctetString value = request.getValue();
394 if (value == null)
395 {
396 throw new LDAPException(ResultCode.DECODING_ERROR,
397 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_NO_VALUE.get());
398 }
399
400 try
401 {
402 final ASN1Element[] elements =
403 ASN1Sequence.decodeAsSequence(value.getValue()).elements();
404 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
405
406 String subject = null;
407 String fullBefore = null;
408 String fullAfter = null;
409 String compactBefore = null;
410 String compactAfter = null;
411 final ArrayList<ObjectPair<String,String>> pdmList =
412 new ArrayList<ObjectPair<String,String>>(10);
413 for (int i=1; i < elements.length; i++)
414 {
415 switch (elements[i].getType())
416 {
417 case MESSAGE_SUBJECT_BER_TYPE:
418 subject =
419 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
420 break;
421
422 case FULL_TEXT_BEFORE_TOKEN_BER_TYPE:
423 fullBefore =
424 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
425 break;
426
427 case FULL_TEXT_AFTER_TOKEN_BER_TYPE:
428 fullAfter =
429 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
430 break;
431
432 case COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE:
433 compactBefore =
434 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
435 break;
436
437 case COMPACT_TEXT_AFTER_TOKEN_BER_TYPE:
438 compactAfter =
439 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue();
440 break;
441
442 case PREFERRED_DELIVERY_MECHANISM_BER_TYPE:
443 final ASN1Element[] pdmElements =
444 ASN1Sequence.decodeAsSequence(elements[i]).elements();
445 for (final ASN1Element e : pdmElements)
446 {
447 final ASN1Element[] mechElements =
448 ASN1Sequence.decodeAsSequence(e).elements();
449 final String mech = ASN1OctetString.decodeAsOctetString(
450 mechElements[0]).stringValue();
451
452 final String recipientID;
453 if (mechElements.length > 1)
454 {
455 recipientID = ASN1OctetString.decodeAsOctetString(
456 mechElements[1]).stringValue();
457 }
458 else
459 {
460 recipientID = null;
461 }
462
463 pdmList.add(new ObjectPair<String,String>(mech, recipientID));
464 }
465 break;
466
467 default:
468 throw new LDAPException(ResultCode.DECODING_ERROR,
469 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_UNEXPECTED_TYPE.get(
470 StaticUtils.toHex(elements[i].getType())));
471 }
472 }
473
474 preferredDeliveryMechanisms = Collections.unmodifiableList(pdmList);
475 messageSubject = subject;
476 fullTextBeforeToken = fullBefore;
477 fullTextAfterToken = fullAfter;
478 compactTextBeforeToken = compactBefore;
479 compactTextAfterToken = compactAfter;
480 }
481 catch (final LDAPException le)
482 {
483 Debug.debugException(le);
484 throw le;
485 }
486 catch (final Exception e)
487 {
488 Debug.debugException(e);
489 throw new LDAPException(ResultCode.DECODING_ERROR,
490 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_ERROR_DECODING_VALUE.get(
491 StaticUtils.getExceptionMessage(e)),
492 e);
493 }
494 }
495
496
497
498 /**
499 * Encodes the provided set of preferred delivery mechanisms into a form
500 * acceptable to the constructor that expects an object pair. All of the
501 * recipient IDs will be {@code null}.
502 *
503 * @param preferredDeliveryMechanisms An optional ordered list of preferred
504 * delivery mechanisms that should be
505 * used to deliver the token to the user.
506 * It may be {@code null} or empty to
507 * allow the server to select an
508 * appropriate delivery mechanism. If it
509 * is non-{@code null} and non-empty,
510 * then only the listed mechanisms will
511 * be considered for use, even if the
512 * server supports alternate mechanisms
513 * not included in this list.
514 *
515 * @return The resulting list of preferred delivery mechanisms with
516 * {@code null} recipient IDs.
517 */
518 private static List<ObjectPair<String,String>> preferredMechanismsToList(
519 final String... preferredDeliveryMechanisms)
520 {
521 if (preferredDeliveryMechanisms == null)
522 {
523 return null;
524 }
525
526 final ArrayList<ObjectPair<String,String>> l =
527 new ArrayList<ObjectPair<String,String>>(
528 preferredDeliveryMechanisms.length);
529 for (final String s : preferredDeliveryMechanisms)
530 {
531 l.add(new ObjectPair<String,String>(s, null));
532 }
533 return l;
534 }
535
536
537
538 /**
539 * Creates an ASN.1 octet string suitable for use as the value of this
540 * extended request.
541 *
542 * @param userDN The DN of the user to whom the
543 * password reset token should be
544 * generated.
545 * @param messageSubject The text (if any) that should be used
546 * as the message subject if the delivery
547 * mechanism accepts a subject. This may
548 * be {@code null} if no subject is
549 * required or a subject should be
550 * automatically generated.
551 * @param fullTextBeforeToken The text (if any) that should appear
552 * before the generated password reset
553 * token in the message delivered to the
554 * user via a delivery mechanism that
555 * does not impose significant
556 * constraints on message size. This may
557 * be {@code null} if no text is required
558 * before the token.
559 * @param fullTextAfterToken The text (if any) that should appear
560 * after the generated password reset
561 * token in the message delivered to the
562 * user via a delivery mechanism that
563 * does not impose significant
564 * constraints on message size. This may
565 * be {@code null} if no text is required
566 * after the token.
567 * @param compactTextBeforeToken The text (if any) that should appear
568 * before the generated password reset
569 * token in the message delivered to the
570 * user via a delivery mechanism that
571 * imposes significant constraints on
572 * message size. This may be
573 * {@code null} if no text is required
574 * before the token.
575 * @param compactTextAfterToken The text (if any) that should appear
576 * after the generated password reset
577 * token in the message delivered to the
578 * user via a delivery mechanism that
579 * imposes significant constraints on
580 * message size. This may be
581 * {@code null} if no text is required
582 * after the token.
583 * @param preferredDeliveryMechanisms An optional ordered list of preferred
584 * delivery mechanisms that should be
585 * used to deliver the token to the user.
586 * It may be {@code null} or empty to
587 * allow the server to select an
588 * appropriate delivery mechanism. If it
589 * is non-{@code null} and non-empty,
590 * then only the listed mechanisms will
591 * be considered for use, even if the
592 * server supports alternate mechanisms
593 * not included in this list. Each
594 * {@code ObjectPair} item must have
595 * a non-{@code null} value for the first
596 * element, which is the name of the
597 * target delivery mechanism. It may
598 * optionally have a non-{@code null}
599 * value for the second element, which is
600 * a recipient ID to use for that
601 * mechanism (e.g., the target mobile
602 * phone number for SMS delivery, an
603 * email address for email delivery,
604 * etc.). If no recipient ID is provided
605 * for a mechanism, then the server will
606 * attempt to select a value for the
607 * user.
608 *
609 * @return The ASN.1 octet string containing the encoded request value.
610 */
611 private static ASN1OctetString encodeValue(final String userDN,
612 final String messageSubject, final String fullTextBeforeToken,
613 final String fullTextAfterToken, final String compactTextBeforeToken,
614 final String compactTextAfterToken,
615 final List<ObjectPair<String,String>> preferredDeliveryMechanisms)
616 {
617 Validator.ensureNotNull(userDN);
618
619 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(7);
620 elements.add(new ASN1OctetString(userDN));
621
622 if (messageSubject != null)
623 {
624 elements.add(new ASN1OctetString(MESSAGE_SUBJECT_BER_TYPE,
625 messageSubject));
626 }
627
628 if (fullTextBeforeToken != null)
629 {
630 elements.add(new ASN1OctetString(FULL_TEXT_BEFORE_TOKEN_BER_TYPE,
631 fullTextBeforeToken));
632 }
633
634 if (fullTextAfterToken != null)
635 {
636 elements.add(new ASN1OctetString(FULL_TEXT_AFTER_TOKEN_BER_TYPE,
637 fullTextAfterToken));
638 }
639
640 if (compactTextBeforeToken != null)
641 {
642 elements.add(new ASN1OctetString(COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE,
643 compactTextBeforeToken));
644 }
645
646 if (compactTextAfterToken != null)
647 {
648 elements.add(new ASN1OctetString(COMPACT_TEXT_AFTER_TOKEN_BER_TYPE,
649 compactTextAfterToken));
650 }
651
652 if ((preferredDeliveryMechanisms != null) &&
653 (! preferredDeliveryMechanisms.isEmpty()))
654 {
655 final ArrayList<ASN1Element> pdmElements =
656 new ArrayList<ASN1Element>(preferredDeliveryMechanisms.size());
657 for (final ObjectPair<String,String> p : preferredDeliveryMechanisms)
658 {
659 if (p.getSecond() == null)
660 {
661 pdmElements.add(new ASN1Sequence(
662 new ASN1OctetString(p.getFirst())));
663 }
664 else
665 {
666 pdmElements.add(new ASN1Sequence(
667 new ASN1OctetString(p.getFirst()),
668 new ASN1OctetString(p.getSecond())));
669 }
670 }
671
672 elements.add(new ASN1Sequence(PREFERRED_DELIVERY_MECHANISM_BER_TYPE,
673 pdmElements));
674 }
675
676 return new ASN1OctetString(new ASN1Sequence(elements).encode());
677 }
678
679
680
681 /**
682 * Retrieves the DN of the user to whom the password reset token should be
683 * delivered.
684 *
685 * @return The DN of the user to whom the password reset token should be
686 * delivered.
687 */
688 public String getUserDN()
689 {
690 return userDN;
691 }
692
693
694
695 /**
696 * Retrieves the text (if any) that should be used as the message subject for
697 * delivery mechanisms that can make use of a subject.
698 *
699 * @return The text that should be used as the message subject for delivery
700 * mechanisms that can make use of a subject, or {@code null} if no
701 * subject should be used, or if the delivery mechanism should
702 * attempt to automatically determine a subject.
703 */
704 public String getMessageSubject()
705 {
706 return messageSubject;
707 }
708
709
710
711 /**
712 * Retrieves the text (if any) that should appear before the single-use token
713 * in the message delivered to the user via a mechanism that does not impose
714 * significant constraints on message size.
715 *
716 * @return The text that should appear before the single-use token in the
717 * message delivered to the user via a mechanism that does not impose
718 * significant constraints on message size, or {@code null} if there
719 * should not be any text before the token.
720 */
721 public String getFullTextBeforeToken()
722 {
723 return fullTextBeforeToken;
724 }
725
726
727
728 /**
729 * Retrieves the text (if any) that should appear after the single-use token
730 * in the message delivered to the user via a mechanism that does not impose
731 * significant constraints on message size.
732 *
733 * @return The text that should appear after the single-use token in the
734 * message delivered to the user via a mechanism that does not impose
735 * significant constraints on message size, or {@code null} if there
736 * should not be any text after the token.
737 */
738 public String getFullTextAfterToken()
739 {
740 return fullTextAfterToken;
741 }
742
743
744
745 /**
746 * Retrieves the text (if any) that should appear before the single-use token
747 * in the message delivered to the user via a mechanism that imposes
748 * significant constraints on message size.
749 *
750 * @return The text that should appear before the single-use token in the
751 * message delivered to the user via a mechanism that imposes
752 * significant constraints on message size, or {@code null} if there
753 * should not be any text before the token.
754 */
755 public String getCompactTextBeforeToken()
756 {
757 return compactTextBeforeToken;
758 }
759
760
761
762 /**
763 * Retrieves the text (if any) that should appear after the single-use token
764 * in the message delivered to the user via a mechanism that imposes
765 * significant constraints on message size.
766 *
767 * @return The text that should appear after the single-use token in the
768 * message delivered to the user via a mechanism that imposes
769 * significant constraints on message size, or {@code null} if there
770 * should not be any text after the token.
771 */
772 public String getCompactTextAfterToken()
773 {
774 return compactTextAfterToken;
775 }
776
777
778
779 /**
780 * Retrieves an ordered list of the preferred delivery mechanisms that should
781 * be used to provide the password reset token to the user, optionally paired
782 * with a mechanism-specific recipient ID (e.g., a mobile phone number for SMS
783 * delivery, or an email address for email delivery) that can be used in the
784 * delivery. If this list is non-empty, then the server will use the first
785 * mechanism in the list that the server supports and is available for the
786 * target user, and the server will only consider mechanisms in the provided
787 * list even if the server supports alternate mechanisms that are not
788 * included. If this list is empty, then the server will attempt to select an
789 * appropriate delivery mechanism for the user.
790 *
791 * @return An ordered list of the preferred delivery mechanisms for the
792 * password reset token, or an empty list if none were provided.
793 */
794 public List<ObjectPair<String,String>> getPreferredDeliveryMechanisms()
795 {
796 return preferredDeliveryMechanisms;
797 }
798
799
800
801 /**
802 * {@inheritDoc}
803 */
804 @Override()
805 public DeliverPasswordResetTokenExtendedResult process(
806 final LDAPConnection connection, final int depth)
807 throws LDAPException
808 {
809 final ExtendedResult extendedResponse = super.process(connection, depth);
810 return new DeliverPasswordResetTokenExtendedResult(extendedResponse);
811 }
812
813
814
815 /**
816 * {@inheritDoc}.
817 */
818 @Override()
819 public DeliverPasswordResetTokenExtendedRequest duplicate()
820 {
821 return duplicate(getControls());
822 }
823
824
825
826 /**
827 * {@inheritDoc}.
828 */
829 @Override()
830 public DeliverPasswordResetTokenExtendedRequest duplicate(
831 final Control[] controls)
832 {
833 final DeliverPasswordResetTokenExtendedRequest r =
834 new DeliverPasswordResetTokenExtendedRequest(userDN,
835 messageSubject, fullTextBeforeToken, fullTextAfterToken,
836 compactTextBeforeToken, compactTextAfterToken,
837 preferredDeliveryMechanisms, controls);
838 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
839 return r;
840 }
841
842
843
844 /**
845 * {@inheritDoc}
846 */
847 @Override()
848 public String getExtendedRequestName()
849 {
850 return INFO_EXTENDED_REQUEST_NAME_DELIVER_PW_RESET_TOKEN.get();
851 }
852
853
854
855 /**
856 * {@inheritDoc}
857 */
858 @Override()
859 public void toString(final StringBuilder buffer)
860 {
861 buffer.append("DeliverPasswordResetTokenExtendedRequest(userDN='");
862 buffer.append(userDN);
863 buffer.append('\'');
864
865 if (messageSubject != null)
866 {
867 buffer.append(", messageSubject='");
868 buffer.append(messageSubject);
869 buffer.append('\'');
870 }
871
872 if (fullTextBeforeToken != null)
873 {
874 buffer.append(", fullTextBeforeToken='");
875 buffer.append(fullTextBeforeToken);
876 buffer.append('\'');
877 }
878
879 if (fullTextAfterToken != null)
880 {
881 buffer.append(", fullTextAfterToken='");
882 buffer.append(fullTextAfterToken);
883 buffer.append('\'');
884 }
885
886 if (compactTextBeforeToken != null)
887 {
888 buffer.append(", compactTextBeforeToken='");
889 buffer.append(compactTextBeforeToken);
890 buffer.append('\'');
891 }
892
893 if (compactTextAfterToken != null)
894 {
895 buffer.append(", compactTextAfterToken='");
896 buffer.append(compactTextAfterToken);
897 buffer.append('\'');
898 }
899
900 if (preferredDeliveryMechanisms != null)
901 {
902 buffer.append(", preferredDeliveryMechanisms={");
903
904 final Iterator<ObjectPair<String,String>> iterator =
905 preferredDeliveryMechanisms.iterator();
906 while (iterator.hasNext())
907 {
908 final ObjectPair<String,String> p = iterator.next();
909 buffer.append('\'');
910 buffer.append(p.getFirst());
911 if (p.getSecond() != null)
912 {
913 buffer.append('(');
914 buffer.append(p.getSecond());
915 buffer.append(')');
916 }
917 buffer.append('\'');
918 if (iterator.hasNext())
919 {
920 buffer.append(',');
921 }
922 }
923 }
924
925 final Control[] controls = getControls();
926 if (controls.length > 0)
927 {
928 buffer.append(", controls={");
929 for (int i=0; i < controls.length; i++)
930 {
931 if (i > 0)
932 {
933 buffer.append(", ");
934 }
935
936 buffer.append(controls[i]);
937 }
938 buffer.append('}');
939 }
940
941 buffer.append(')');
942 }
943 }