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