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