001    /*
002     * Copyright 2013-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.io.ByteArrayInputStream;
026    import java.io.InputStream;
027    
028    import com.unboundid.asn1.ASN1Element;
029    import com.unboundid.asn1.ASN1Enumerated;
030    import com.unboundid.asn1.ASN1OctetString;
031    import com.unboundid.asn1.ASN1Sequence;
032    import com.unboundid.ldap.sdk.Control;
033    import com.unboundid.ldap.sdk.ExtendedResult;
034    import com.unboundid.ldap.sdk.LDAPException;
035    import com.unboundid.ldap.sdk.ResultCode;
036    import com.unboundid.util.Debug;
037    import com.unboundid.util.StaticUtils;
038    import com.unboundid.util.ThreadSafety;
039    import com.unboundid.util.ThreadSafetyLevel;
040    import com.unboundid.util.Validator;
041    
042    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
043    
044    
045    
046    /**
047     * <BLOCKQUOTE>
048     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
049     *   LDAP SDK for Java.  It is not available for use in applications that
050     *   include only the Standard Edition of the LDAP SDK, and is not supported for
051     *   use in conjunction with non-UnboundID products.
052     * </BLOCKQUOTE>
053     * This class provides an implementation of an extended result that can be used
054     * to retrieve a version of the server configuration.
055     * <BR><BR>
056     * The OID for this extended result is 1.3.6.1.4.1.30221.2.6.29.  If the request
057     * was processed successfully, then the response will have a value with the
058     * following encoding:
059     * <PRE>
060     *   GetConfigurationResult ::= SEQUENCE {
061     *        configurationType         [0] ENUMERATED {
062     *             active       (0),
063     *             baseline     (1),
064     *             archived     (2),
065     *             ... },
066     *        fileName                  [1] OCTET STRING,
067     *        configurationFileData     [2] OCTET STRING,
068     *        ... }
069     * </PRE>
070     *
071     * @see  GetConfigurationExtendedRequest
072     * @see  ListConfigurationsExtendedRequest
073     */
074    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
075    public final class GetConfigurationExtendedResult
076           extends ExtendedResult
077    {
078      /**
079       * The OID (1.3.6.1.4.1.30221.2.6.29) for the get configuration extended
080       * result.
081       */
082      public static final String GET_CONFIG_RESULT_OID = "1.3.6.1.4.1.30221.2.6.29";
083    
084    
085    
086      /**
087       * The BER type for the element holding the type of configuration that has
088       * been returned.
089       */
090      private static final byte TYPE_CONFIG_TYPE = (byte) 0x80;
091    
092    
093    
094      /**
095       * The BER type for the element holding the name of the configuration file
096       * that has been returned.
097       */
098      private static final byte TYPE_FILE_NAME = (byte) 0x81;
099    
100    
101    
102      /**
103       * The BER type for the element holding the raw LDIF data that comprises the
104       * configuration file that has been returned.
105       */
106      private static final byte TYPE_FILE_DATA = (byte) 0x82;
107    
108    
109    
110      /**
111       * The serial version UID for this serializable class.
112       */
113      private static final long serialVersionUID = 6042324433827773678L;
114    
115    
116    
117      // The raw data for the configuration file that has been returned.
118      private final byte[] fileData;
119    
120      // The type of configuration that has been returned.
121      private final GetConfigurationType configurationType;
122    
123      // The name of the configuration file that has been returned.
124      private final String fileName;
125    
126    
127    
128      /**
129       * Creates a new get configuration extended result from the provided generic
130       * extended result.
131       *
132       * @param  result  The generic extended result to be decoded as a get
133       *                 configuration extended result.
134       *
135       * @throws LDAPException  If the provided extended result cannot be parsed as
136       *                         a valid get configuration extended result.
137       */
138      public GetConfigurationExtendedResult(final ExtendedResult result)
139           throws LDAPException
140      {
141        super(result);
142    
143        final ASN1OctetString value = result.getValue();
144        if (value == null)
145        {
146          configurationType = null;
147          fileName = null;
148          fileData = null;
149          return;
150        }
151    
152        try
153        {
154          final ASN1Element[] elements =
155               ASN1Sequence.decodeAsSequence(value.getValue()).elements();
156    
157          final int configType =
158               ASN1Enumerated.decodeAsEnumerated(elements[0]).intValue();
159          configurationType = GetConfigurationType.forIntValue(configType);
160          if (configurationType == null)
161          {
162            throw new LDAPException(ResultCode.DECODING_ERROR,
163                 ERR_GET_CONFIG_RESULT_INVALID_CONFIG_TYPE.get(configType));
164          }
165    
166          fileName = ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
167          fileData = ASN1OctetString.decodeAsOctetString(elements[2]).getValue();
168        }
169        catch (final LDAPException le)
170        {
171          Debug.debugException(le);
172          throw le;
173        }
174        catch (final Exception e)
175        {
176          Debug.debugException(e);
177          throw new LDAPException(ResultCode.DECODING_ERROR,
178               ERR_GET_CONFIG_RESULT_ERROR_PARSING_VALUE.get(
179                    StaticUtils.getExceptionMessage(e)),
180               e);
181        }
182      }
183    
184    
185    
186      /**
187       * Creates a new get configuration extended result with the provided
188       * information.
189       *
190       * @param  messageID          The message ID for the LDAP message that is
191       *                            associated with this LDAP result.
192       * @param  resultCode         The result code from the response.
193       * @param  diagnosticMessage  The diagnostic message from the response, if
194       *                            available.
195       * @param  matchedDN          The matched DN from the response, if available.
196       * @param  referralURLs       The set of referral URLs from the response, if
197       *                            available.
198       * @param  configurationType  The type of configuration that has been
199       *                            returned.
200       * @param  fileName           The name of the configuration file that has been
201       *                            returned.
202       * @param  fileData           The raw data for the configuration file that has
203       *                            been returned.
204       * @param  responseControls   The set of controls from the response, if
205       *                            available.
206       */
207      public GetConfigurationExtendedResult(final int messageID,
208                  final ResultCode resultCode, final String diagnosticMessage,
209                  final String matchedDN, final String[] referralURLs,
210                  final GetConfigurationType configurationType,
211                  final String fileName, final byte[] fileData,
212                  final Control... responseControls)
213      {
214        super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
215             ((configurationType == null) ? null : GET_CONFIG_RESULT_OID),
216             encodeValue(configurationType, fileName, fileData), responseControls);
217    
218        this.configurationType = configurationType;
219        this.fileName          = fileName;
220        this.fileData          = fileData;
221      }
222    
223    
224    
225      /**
226       * Creates an ASN.1 octet string containing an encoded representation of the
227       * value for a get configuration extended result with the provided
228       * information.
229       *
230       * @param  configurationType  The type of configuration that has been
231       *                            returned.
232       * @param  fileName           The name of the configuration file that has been
233       *                            returned.
234       * @param  fileData           The raw data for the configuration file that has
235       *                            been returned.
236       *
237       * @return  An ASN.1 octet string containing an encoded representation of the
238       *          value for a get configuration extended result, or {@code null} if
239       *          a result with the provided information should not have a value.
240       */
241      public static ASN1OctetString encodeValue(
242                         final GetConfigurationType configurationType,
243                         final String fileName, final byte[] fileData)
244      {
245        if (configurationType == null)
246        {
247          Validator.ensureTrue((fileName == null),
248               "The configuration file name must be null if the configuration " +
249                    "type is null.");
250          Validator.ensureTrue((fileData == null),
251               "The configuration file data must be null if the configuration " +
252                    "type is null.");
253          return null;
254        }
255    
256        Validator.ensureTrue((fileName != null),
257             "The configuration file name must not be null if the configuration " +
258                  "type is not null.");
259        Validator.ensureTrue((fileData != null),
260             "The configuration file data must not be null if the configuration " +
261                  "type is not null.");
262    
263        final ASN1Sequence valueSequence = new ASN1Sequence(
264             new ASN1Enumerated(TYPE_CONFIG_TYPE, configurationType.getIntValue()),
265             new ASN1OctetString(TYPE_FILE_NAME, fileName),
266             new ASN1OctetString(TYPE_FILE_DATA, fileData));
267        return new ASN1OctetString(valueSequence.encode());
268      }
269    
270    
271    
272      /**
273       * Retrieves the type of configuration that has been returned, if available.
274       *
275       * @return  The type of configuration that has been returned, or {@code null}
276       *          if this is not available.
277       */
278      public GetConfigurationType getConfigurationType()
279      {
280        return configurationType;
281      }
282    
283    
284    
285      /**
286       * Retrieves the name of the configuration file that has been returned, if
287       * available.
288       *
289       * @return  The name of the configuration file that has been returned, or
290       *          {@code null} if this is not available.
291       */
292      public String getFileName()
293      {
294        return fileName;
295      }
296    
297    
298    
299      /**
300       * Retrieves the raw data for the configuration file that has been returned,
301       * if available.
302       *
303       * @return  The raw data for the configuration file that has been returned,
304       *          or {@code null} if this is not available.
305       */
306      public byte[] getFileData()
307      {
308        return fileData;
309      }
310    
311    
312    
313      /**
314       * Retrieves an input stream that may be used to read the file data that has
315       * been returned, if available.
316       *
317       * @return  An input stream that may be used to read the file data that has
318       *          been returned, or {@code null} if this is not available.
319       */
320      public InputStream getFileDataInputStream()
321      {
322        if (fileData == null)
323        {
324          return null;
325        }
326        else
327        {
328          return new ByteArrayInputStream(fileData);
329        }
330      }
331    
332    
333    
334      /**
335       * {@inheritDoc}
336       */
337      @Override()
338      public String getExtendedResultName()
339      {
340        return INFO_EXTENDED_RESULT_NAME_GET_CONFIG.get();
341      }
342    
343    
344    
345      /**
346       * {@inheritDoc}
347       */
348      @Override()
349      public void toString(final StringBuilder buffer)
350      {
351        buffer.append("GetConfigurationExtendedResult(resultCode=");
352        buffer.append(getResultCode());
353    
354        final int messageID = getMessageID();
355        if (messageID >= 0)
356        {
357          buffer.append(", messageID=");
358          buffer.append(messageID);
359        }
360    
361        if (configurationType != null)
362        {
363          buffer.append(", configType=");
364          buffer.append(configurationType.name());
365        }
366    
367        if (fileName != null)
368        {
369          buffer.append(", fileName='");
370          buffer.append(fileName);
371          buffer.append('\'');
372        }
373    
374        if (fileData != null)
375        {
376          buffer.append(", fileLength=");
377          buffer.append(fileData.length);
378        }
379    
380        final String diagnosticMessage = getDiagnosticMessage();
381        if (diagnosticMessage != null)
382        {
383          buffer.append(", diagnosticMessage='");
384          buffer.append(diagnosticMessage);
385          buffer.append('\'');
386        }
387    
388        final String matchedDN = getMatchedDN();
389        if (matchedDN != null)
390        {
391          buffer.append(", matchedDN='");
392          buffer.append(matchedDN);
393          buffer.append('\'');
394        }
395    
396        final String[] referralURLs = getReferralURLs();
397        if (referralURLs.length > 0)
398        {
399          buffer.append(", referralURLs={");
400          for (int i=0; i < referralURLs.length; i++)
401          {
402            if (i > 0)
403            {
404              buffer.append(", ");
405            }
406    
407            buffer.append('\'');
408            buffer.append(referralURLs[i]);
409            buffer.append('\'');
410          }
411          buffer.append('}');
412        }
413    
414        final Control[] responseControls = getResponseControls();
415        if (responseControls.length > 0)
416        {
417          buffer.append(", responseControls={");
418          for (int i=0; i < responseControls.length; i++)
419          {
420            if (i > 0)
421            {
422              buffer.append(", ");
423            }
424    
425            buffer.append(responseControls[i]);
426          }
427          buffer.append('}');
428        }
429    
430        buffer.append(')');
431      }
432    }