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