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.util.ArrayList;
026
027import com.unboundid.asn1.ASN1Element;
028import com.unboundid.asn1.ASN1Null;
029import com.unboundid.asn1.ASN1OctetString;
030import com.unboundid.asn1.ASN1Sequence;
031import com.unboundid.ldap.sdk.Control;
032import com.unboundid.ldap.sdk.ExtendedRequest;
033import com.unboundid.ldap.sdk.ExtendedResult;
034import com.unboundid.ldap.sdk.LDAPConnection;
035import com.unboundid.ldap.sdk.LDAPException;
036import com.unboundid.ldap.sdk.ResultCode;
037import com.unboundid.util.Debug;
038import com.unboundid.util.StaticUtils;
039import com.unboundid.util.ThreadSafety;
040import com.unboundid.util.ThreadSafetyLevel;
041import com.unboundid.util.Validator;
042
043import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
044
045
046
047/**
048 * This class provides an implementation of an extended request that can be used
049 * to retrieve a version of the server configuration.  It may be the active
050 * configuration, the baseline configuration, or any of the archived
051 * configurations.  The set of available configurations that may be retrieved
052 * can be obtained using the {@link ListConfigurationsExtendedRequest}.
053 * <BR>
054 * <BLOCKQUOTE>
055 *   <B>NOTE:</B>  This class, and other classes within the
056 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
057 *   supported for use against Ping Identity, UnboundID, and
058 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
059 *   for proprietary functionality or for external specifications that are not
060 *   considered stable or mature enough to be guaranteed to work in an
061 *   interoperable way with other types of LDAP servers.
062 * </BLOCKQUOTE>
063 * <BR>
064 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.28.  It must have
065 * a value with the following encoding:
066 * <PRE>
067 *   GetConfigurationRequest ::= SEQUENCE {
068 *        requestType     CHOICE {
069 *             activeConfiguration       [0] NULL,
070 *             baselineConfiguration     [1] OCTET STRING,
071 *             archivedConfiguration     [2] OCTET STRING,
072 *             ... },
073 *        ... }
074 * </PRE>
075 */
076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
077public final class GetConfigurationExtendedRequest
078       extends ExtendedRequest
079{
080  /**
081   * The OID (1.3.6.1.4.1.30221.2.6.28) for the get configuration extended
082   * request.
083   */
084  public static final  String GET_CONFIG_REQUEST_OID =
085       "1.3.6.1.4.1.30221.2.6.28";
086
087
088
089  /**
090   * The serial version UID for this serializable class.
091   */
092  private static final long   serialVersionUID       = 2953462215986675988L;
093
094
095
096  // The type of configuration that should be retrieved.
097  private final GetConfigurationType configurationType;
098
099  // The name of the configuration file that should be retrieved.
100  private final String fileName;
101
102
103
104  /**
105   * Creates a new get configuration extended request that has been decoded from
106   * the provided generic extended request.
107   *
108   * @param  r  The generic extended request to decode as a get configuration
109   *            extended request.
110   *
111   * @throws LDAPException  If the provided request cannot be decoded as a get
112   *                         configuration extended request.
113   */
114  public GetConfigurationExtendedRequest(final ExtendedRequest r)
115       throws LDAPException
116  {
117    super(r);
118
119    final ASN1OctetString value = r.getValue();
120    if (value == null)
121    {
122      throw new LDAPException(ResultCode.DECODING_ERROR,
123           ERR_GET_CONFIG_REQUEST_NO_VALUE.get());
124    }
125
126    try
127    {
128      final ASN1Element[] elements =
129           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
130      switch (elements[0].getType())
131      {
132        case GetConfigurationType.ACTIVE_BER_TYPE:
133          configurationType = GetConfigurationType.ACTIVE;
134          fileName = null;
135          break;
136        case GetConfigurationType.BASELINE_BER_TYPE:
137          configurationType = GetConfigurationType.BASELINE;
138          fileName =
139               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
140          break;
141        case GetConfigurationType.ARCHIVED_BER_TYPE:
142          configurationType = GetConfigurationType.ARCHIVED;
143          fileName =
144               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
145          break;
146        default:
147          throw new LDAPException(ResultCode.DECODING_ERROR,
148               ERR_GET_CONFIG_REQUEST_UNEXPECTED_CONFIG_TYPE.get(
149                    StaticUtils.toHex(elements[0].getType())));
150      }
151    }
152    catch (final LDAPException le)
153    {
154      Debug.debugException(le);
155      throw le;
156    }
157    catch (final Exception e)
158    {
159      Debug.debugException(e);
160      throw new LDAPException(ResultCode.DECODING_ERROR,
161           ERR_GET_CONFIG_REQUEST_ERROR_PARSING_VALUE.get(
162                StaticUtils.getExceptionMessage(e)),
163           e);
164    }
165  }
166
167
168
169  /**
170   * Creates a new get configuration extended request with the provided
171   * information.
172   *
173   * @param  configurationType  The type of configuration that should be
174   *                            retrieved.
175   * @param  fileName           The name of the configuration file that should
176   *                            be retrieved, if appropriate.
177   * @param  controls           An optional set of controls to include in the
178   *                            request.  This may be {@code null} or empty if
179   *                            no controls should be included in the request.
180   */
181  private GetConfigurationExtendedRequest(
182               final GetConfigurationType configurationType,
183               final String fileName, final Control... controls)
184  {
185    super(GET_CONFIG_REQUEST_OID, encodeValue(configurationType, fileName),
186         controls);
187
188    this.configurationType = configurationType;
189    this.fileName          = fileName;
190  }
191
192
193
194  /**
195   * Encodes the provided information into a format suitable for use as the
196   * value of this extended request.
197   *
198   * @param  configurationType  The type of configuration that should be
199   *                            retrieved.
200   * @param  fileName           The name of the configuration file that should
201   *                            be retrieved, if appropriate.
202   *
203   * @return  The ASN.1 octet string containing the encoded representation of
204   *          the provided information.
205   */
206  private static ASN1OctetString encodeValue(
207                      final GetConfigurationType configurationType,
208                      final String fileName)
209  {
210    final ArrayList<ASN1Element> elements = new ArrayList<>(0);
211    switch (configurationType)
212    {
213      case ACTIVE:
214        elements.add(new ASN1Null(configurationType.getBERType()));
215        break;
216
217      case BASELINE:
218      case ARCHIVED:
219        elements.add(
220             new ASN1OctetString(configurationType.getBERType(), fileName));
221        break;
222
223      default:
224        // This should never happen.
225        return null;
226    }
227
228    return new ASN1OctetString(new ASN1Sequence(elements).encode());
229  }
230
231
232
233  /**
234   * Creates a new get configuration extended request that may be used to
235   * retrieve the current active configuration.
236   *
237   * @param  controls  An optional set of controls to include in the request.
238   *                   This may be {@code null} or empty if no controls should
239   *                   be included in the request.
240   *
241   * @return  The get configuration extended request that has been created.
242   */
243  public static GetConfigurationExtendedRequest
244                     createGetActiveConfigurationRequest(
245                          final Control... controls)
246  {
247    return new GetConfigurationExtendedRequest(GetConfigurationType.ACTIVE,
248         null, controls);
249  }
250
251
252
253  /**
254   * Creates a new get configuration extended request that may be used to
255   * retrieve the baseline configuration for the current server version.
256   *
257   * @param  fileName  The name of the archived configuration file to retrieve.
258   *                   This must not be {@code null}.
259   * @param  controls  An optional set of controls to include in the request.
260   *                   This may be {@code null} or empty if no controls should
261   *                   be included in the request.
262   *
263   * @return  The get configuration extended request that has been created.
264   */
265  public static GetConfigurationExtendedRequest
266                     createGetBaselineConfigurationRequest(
267                          final String fileName, final Control... controls)
268  {
269    Validator.ensureNotNull(fileName);
270
271    return new GetConfigurationExtendedRequest(GetConfigurationType.BASELINE,
272         fileName, controls);
273  }
274
275
276
277  /**
278   * Creates a new get configuration extended request that may be used to
279   * retrieve the baseline configuration for the current server version.
280   *
281   * @param  fileName  The name of the archived configuration file to retrieve.
282   *                   This must not be {@code null}.
283   * @param  controls  An optional set of controls to include in the request.
284   *                   This may be {@code null} or empty if no controls should
285   *                   be included in the request.
286   *
287   * @return  The get configuration extended request that has been created.
288   */
289  public static GetConfigurationExtendedRequest
290                     createGetArchivedConfigurationRequest(
291                          final String fileName, final Control... controls)
292  {
293    Validator.ensureNotNull(fileName);
294
295    return new GetConfigurationExtendedRequest(GetConfigurationType.ARCHIVED,
296         fileName, controls);
297  }
298
299
300
301  /**
302   * Retrieves the type of configuration file that should be requested.
303   *
304   * @return  The type of configuration file that should be requested.
305   */
306  public GetConfigurationType getConfigurationType()
307  {
308    return configurationType;
309  }
310
311
312
313  /**
314   * Retrieves the name of the configuration file that should be requested, if
315   * applicable.  This will only be available for requests that intend to
316   * retrieve a baseline or archived configuration.
317   *
318   * @return  The name of the configuration file that should be requested, or
319   *          {@code null} if this is not applicable.
320   */
321  public String getFileName()
322  {
323    return fileName;
324  }
325
326
327
328  /**
329   * {@inheritDoc}
330   */
331  @Override()
332  public GetConfigurationExtendedResult process(
333              final LDAPConnection connection, final int depth)
334         throws LDAPException
335  {
336    final ExtendedResult extendedResponse = super.process(connection, depth);
337    return new GetConfigurationExtendedResult(extendedResponse);
338  }
339
340
341
342  /**
343   * {@inheritDoc}
344   */
345  @Override()
346  public GetConfigurationExtendedRequest duplicate()
347  {
348    return duplicate(getControls());
349  }
350
351
352
353  /**
354   * {@inheritDoc}
355   */
356  @Override()
357  public GetConfigurationExtendedRequest duplicate(final Control[] controls)
358  {
359    final GetConfigurationExtendedRequest r =
360         new GetConfigurationExtendedRequest(configurationType, fileName,
361              controls);
362    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
363    return r;
364  }
365
366
367
368  /**
369   * {@inheritDoc}
370   */
371  @Override()
372  public String getExtendedRequestName()
373  {
374    return INFO_EXTENDED_REQUEST_NAME_GET_CONFIG.get();
375  }
376
377
378
379  /**
380   * {@inheritDoc}
381   */
382  @Override()
383  public void toString(final StringBuilder buffer)
384  {
385    buffer.append("GetConfigurationsExtendedRequest(configType=");
386    buffer.append(configurationType.name());
387
388    if (fileName != null)
389    {
390      buffer.append(", fileName='");
391      buffer.append(fileName);
392      buffer.append('\'');
393    }
394
395    final Control[] controls = getControls();
396    if (controls.length > 0)
397    {
398      buffer.append(", controls={");
399      for (int i=0; i < controls.length; i++)
400      {
401        if (i > 0)
402        {
403          buffer.append(", ");
404        }
405
406        buffer.append(controls[i]);
407      }
408      buffer.append('}');
409    }
410
411    buffer.append(')');
412  }
413}