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