001    /*
002     * Copyright 2007-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-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.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    }