001 /*
002 * Copyright 2007-2013 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2013 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.extensions;
022
023
024 import com.unboundid.asn1.ASN1Element;
025 import com.unboundid.asn1.ASN1OctetString;
026 import com.unboundid.asn1.ASN1Sequence;
027 import com.unboundid.ldap.sdk.Control;
028 import com.unboundid.ldap.sdk.ExtendedResult;
029 import com.unboundid.ldap.sdk.LDAPException;
030 import com.unboundid.ldap.sdk.ResultCode;
031 import com.unboundid.util.NotMutable;
032 import com.unboundid.util.ThreadSafety;
033 import com.unboundid.util.ThreadSafetyLevel;
034
035 import static com.unboundid.ldap.sdk.extensions.ExtOpMessages.*;
036 import 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)
050 public 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 }