001/* 002 * Copyright 2007-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 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 */ 021package com.unboundid.ldap.sdk.extensions; 022 023 024import com.unboundid.asn1.ASN1Element; 025import com.unboundid.asn1.ASN1OctetString; 026import com.unboundid.asn1.ASN1Sequence; 027import com.unboundid.ldap.sdk.Control; 028import com.unboundid.ldap.sdk.ExtendedResult; 029import com.unboundid.ldap.sdk.LDAPException; 030import com.unboundid.ldap.sdk.ResultCode; 031import com.unboundid.util.NotMutable; 032import com.unboundid.util.ThreadSafety; 033import com.unboundid.util.ThreadSafetyLevel; 034 035import static com.unboundid.ldap.sdk.extensions.ExtOpMessages.*; 036import static com.unboundid.util.Debug.*; 037 038 039 040/** 041 * This class implements a data structure for storing the information from an 042 * extended result for the password modify extended request as defined in 043 * <A HREF="http://www.ietf.org/rfc/rfc3062.txt">RFC 3062</A>. It is identical 044 * to the standard {@link ExtendedResult} object except that it is also able to 045 * extract the generated password if one was included. See the documentation 046 * for the {@link PasswordModifyExtendedRequest} class for an example of this. 047 */ 048@NotMutable() 049@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 050public final class PasswordModifyExtendedResult 051 extends ExtendedResult 052{ 053 /** 054 * The serial version UID for this serializable class. 055 */ 056 private static final long serialVersionUID = -160274020063799410L; 057 058 059 060 // The generated password from the response, if applicable. 061 private final ASN1OctetString generatedPassword; 062 063 064 065 /** 066 * Creates a new password modify extended result from the provided extended 067 * result. 068 * 069 * @param extendedResult The extended result to be decoded as a password 070 * modify extended result. It must not be 071 * {@code null}. 072 * 073 * @throws LDAPException If the provided extended result cannot be decoded 074 * as a password modify extended result. 075 */ 076 public PasswordModifyExtendedResult(final ExtendedResult extendedResult) 077 throws LDAPException 078 { 079 super(extendedResult); 080 081 final ASN1OctetString value = extendedResult.getValue(); 082 if (value == null) 083 { 084 generatedPassword = null; 085 return; 086 } 087 088 final ASN1Element[] elements; 089 try 090 { 091 final ASN1Element valueElement = ASN1Element.decode(value.getValue()); 092 elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); 093 } 094 catch (Exception e) 095 { 096 debugException(e); 097 throw new LDAPException(ResultCode.DECODING_ERROR, 098 ERR_PW_MODIFY_RESPONSE_VALUE_NOT_SEQUENCE.get(e), 099 e); 100 } 101 102 if (elements.length == 0) 103 { 104 generatedPassword = null; 105 return; 106 } 107 else if (elements.length != 1) 108 { 109 throw new LDAPException(ResultCode.DECODING_ERROR, 110 ERR_PW_MODIFY_RESPONSE_MULTIPLE_ELEMENTS.get()); 111 } 112 113 generatedPassword = ASN1OctetString.decodeAsOctetString(elements[0]); 114 } 115 116 117 118 /** 119 * Creates a new password modify extended result with the provided 120 * 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. 125 * @param diagnosticMessage The diagnostic message from the response, if 126 * available. 127 * @param matchedDN The matched DN from the response, if available. 128 * @param referralURLs The set of referral URLs from the response, if 129 * available. 130 * @param generatedPassword The generated password for this response, if 131 * available. 132 * @param responseControls The set of controls from the response, if 133 * available. 134 */ 135 public PasswordModifyExtendedResult(final int messageID, 136 final ResultCode resultCode, 137 final String diagnosticMessage, 138 final String matchedDN, 139 final String[] referralURLs, 140 final ASN1OctetString generatedPassword, 141 final Control[] responseControls) 142 { 143 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs, 144 null, encodeValue(generatedPassword), responseControls); 145 146 this.generatedPassword = generatedPassword; 147 } 148 149 150 151 /** 152 * Encodes the value for this extended result using the provided information. 153 * 154 * @param generatedPassword The generated password for this response, if 155 * available. 156 * 157 * @return An ASN.1 octet string containing the encoded value, or 158 * {@code null} if there should not be an encoded value. 159 */ 160 private static ASN1OctetString 161 encodeValue(final ASN1OctetString generatedPassword) 162 { 163 if (generatedPassword == null) 164 { 165 return null; 166 } 167 168 final ASN1Element[] elements = 169 { 170 new ASN1OctetString((byte) 0x80, generatedPassword.getValue()) 171 }; 172 173 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 174 } 175 176 177 178 /** 179 * Retrieves the string representation of the generated password contained in 180 * this extended result, if available. 181 * 182 * @return The string representation of the generated password contained in 183 * this extended result, or {@code null} if no generated password was 184 * included in the extended result. 185 */ 186 public String getGeneratedPassword() 187 { 188 if (generatedPassword == null) 189 { 190 return null; 191 } 192 else 193 { 194 return generatedPassword.stringValue(); 195 } 196 } 197 198 199 200 /** 201 * Retrieves the binary representation of the generated password contained in 202 * this extended result, if available. 203 * 204 * @return The binary representation of the generated password contained in 205 * this extended result, or {@code null} if no generated password was 206 * included in the extended result. 207 */ 208 public byte[] getGeneratedPasswordBytes() 209 { 210 if (generatedPassword == null) 211 { 212 return null; 213 } 214 else 215 { 216 return generatedPassword.getValue(); 217 } 218 } 219 220 221 222 /** 223 * Retrieves the raw generated password contained in this extended result, if 224 * available. 225 * 226 * @return The raw generated password contained in this extended result, or 227 * {@code null} if no generated password was included in the extended 228 * result. 229 */ 230 public ASN1OctetString getRawGeneratedPassword() 231 { 232 return generatedPassword; 233 } 234 235 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override() 241 public String getExtendedResultName() 242 { 243 return INFO_EXTENDED_RESULT_NAME_PASSWORD_MODIFY.get(); 244 } 245 246 247 248 /** 249 * Appends a string representation of this extended result to the provided 250 * buffer. 251 * 252 * @param buffer The buffer to which a string representation of this 253 * extended result will be appended. 254 */ 255 @Override() 256 public void toString(final StringBuilder buffer) 257 { 258 buffer.append("PasswordModifyExtendedResult(resultCode="); 259 buffer.append(getResultCode()); 260 261 final int messageID = getMessageID(); 262 if (messageID >= 0) 263 { 264 buffer.append(", messageID="); 265 buffer.append(messageID); 266 } 267 268 if (generatedPassword != null) 269 { 270 buffer.append(", generatedPassword='"); 271 buffer.append(generatedPassword.stringValue()); 272 buffer.append('\''); 273 } 274 275 final String diagnosticMessage = getDiagnosticMessage(); 276 if (diagnosticMessage != null) 277 { 278 buffer.append(", diagnosticMessage='"); 279 buffer.append(diagnosticMessage); 280 buffer.append('\''); 281 } 282 283 final String matchedDN = getMatchedDN(); 284 if (matchedDN != null) 285 { 286 buffer.append(", matchedDN='"); 287 buffer.append(matchedDN); 288 buffer.append('\''); 289 } 290 291 final String[] referralURLs = getReferralURLs(); 292 if (referralURLs.length > 0) 293 { 294 buffer.append(", referralURLs={"); 295 for (int i=0; i < referralURLs.length; i++) 296 { 297 if (i > 0) 298 { 299 buffer.append(", "); 300 } 301 302 buffer.append('\''); 303 buffer.append(referralURLs[i]); 304 buffer.append('\''); 305 } 306 buffer.append('}'); 307 } 308 309 final Control[] responseControls = getResponseControls(); 310 if (responseControls.length > 0) 311 { 312 buffer.append(", responseControls={"); 313 for (int i=0; i < responseControls.length; i++) 314 { 315 if (i > 0) 316 { 317 buffer.append(", "); 318 } 319 320 buffer.append(responseControls[i]); 321 } 322 buffer.append('}'); 323 } 324 325 buffer.append(')'); 326 } 327}