001/*
002 * Copyright 2013-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2013-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.extensions;
037
038
039
040import java.util.ArrayList;
041
042import com.unboundid.asn1.ASN1Element;
043import com.unboundid.asn1.ASN1Null;
044import com.unboundid.asn1.ASN1OctetString;
045import com.unboundid.asn1.ASN1Sequence;
046import com.unboundid.ldap.sdk.Control;
047import com.unboundid.ldap.sdk.ExtendedRequest;
048import com.unboundid.ldap.sdk.ExtendedResult;
049import com.unboundid.ldap.sdk.LDAPConnection;
050import com.unboundid.ldap.sdk.LDAPException;
051import com.unboundid.ldap.sdk.ResultCode;
052import com.unboundid.util.Debug;
053import com.unboundid.util.NotNull;
054import com.unboundid.util.Nullable;
055import com.unboundid.util.StaticUtils;
056import com.unboundid.util.ThreadSafety;
057import com.unboundid.util.ThreadSafetyLevel;
058import com.unboundid.util.Validator;
059
060import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
061
062
063
064/**
065 * This class provides an implementation of an extended request that can be used
066 * to retrieve a version of the server configuration.  It may be the active
067 * configuration, the baseline configuration, or any of the archived
068 * configurations.  The set of available configurations that may be retrieved
069 * can be obtained using the {@link ListConfigurationsExtendedRequest}.
070 * <BR>
071 * <BLOCKQUOTE>
072 *   <B>NOTE:</B>  This class, and other classes within the
073 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
074 *   supported for use against Ping Identity, UnboundID, and
075 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
076 *   for proprietary functionality or for external specifications that are not
077 *   considered stable or mature enough to be guaranteed to work in an
078 *   interoperable way with other types of LDAP servers.
079 * </BLOCKQUOTE>
080 * <BR>
081 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.28.  It must have
082 * a value with the following encoding:
083 * <PRE>
084 *   GetConfigurationRequest ::= SEQUENCE {
085 *        requestType     CHOICE {
086 *             activeConfiguration       [0] NULL,
087 *             baselineConfiguration     [1] OCTET STRING,
088 *             archivedConfiguration     [2] OCTET STRING,
089 *             ... },
090 *        ... }
091 * </PRE>
092 */
093@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
094public final class GetConfigurationExtendedRequest
095       extends ExtendedRequest
096{
097  /**
098   * The OID (1.3.6.1.4.1.30221.2.6.28) for the get configuration extended
099   * request.
100   */
101  @NotNull public static final String GET_CONFIG_REQUEST_OID =
102       "1.3.6.1.4.1.30221.2.6.28";
103
104
105
106  /**
107   * The serial version UID for this serializable class.
108   */
109  private static final long   serialVersionUID       = 2953462215986675988L;
110
111
112
113  // The type of configuration that should be retrieved.
114  @NotNull private final GetConfigurationType configurationType;
115
116  // The name of the configuration file that should be retrieved.
117  @Nullable private final String fileName;
118
119
120
121  /**
122   * Creates a new get configuration extended request that has been decoded from
123   * the provided generic extended request.
124   *
125   * @param  r  The generic extended request to decode as a get configuration
126   *            extended request.
127   *
128   * @throws LDAPException  If the provided request cannot be decoded as a get
129   *                         configuration extended request.
130   */
131  public GetConfigurationExtendedRequest(@NotNull final ExtendedRequest r)
132       throws LDAPException
133  {
134    super(r);
135
136    final ASN1OctetString value = r.getValue();
137    if (value == null)
138    {
139      throw new LDAPException(ResultCode.DECODING_ERROR,
140           ERR_GET_CONFIG_REQUEST_NO_VALUE.get());
141    }
142
143    try
144    {
145      final ASN1Element[] elements =
146           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
147      switch (elements[0].getType())
148      {
149        case GetConfigurationType.ACTIVE_BER_TYPE:
150          configurationType = GetConfigurationType.ACTIVE;
151          fileName = null;
152          break;
153        case GetConfigurationType.BASELINE_BER_TYPE:
154          configurationType = GetConfigurationType.BASELINE;
155          fileName =
156               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
157          break;
158        case GetConfigurationType.ARCHIVED_BER_TYPE:
159          configurationType = GetConfigurationType.ARCHIVED;
160          fileName =
161               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
162          break;
163        default:
164          throw new LDAPException(ResultCode.DECODING_ERROR,
165               ERR_GET_CONFIG_REQUEST_UNEXPECTED_CONFIG_TYPE.get(
166                    StaticUtils.toHex(elements[0].getType())));
167      }
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_REQUEST_ERROR_PARSING_VALUE.get(
179                StaticUtils.getExceptionMessage(e)),
180           e);
181    }
182  }
183
184
185
186  /**
187   * Creates a new get configuration extended request with the provided
188   * information.
189   *
190   * @param  configurationType  The type of configuration that should be
191   *                            retrieved.
192   * @param  fileName           The name of the configuration file that should
193   *                            be retrieved, if appropriate.
194   * @param  controls           An optional set of controls to include in the
195   *                            request.  This may be {@code null} or empty if
196   *                            no controls should be included in the request.
197   */
198  private GetConfigurationExtendedRequest(
199               @NotNull final GetConfigurationType configurationType,
200               @Nullable final String fileName,
201               @Nullable final Control... controls)
202  {
203    super(GET_CONFIG_REQUEST_OID, encodeValue(configurationType, fileName),
204         controls);
205
206    this.configurationType = configurationType;
207    this.fileName          = fileName;
208  }
209
210
211
212  /**
213   * Encodes the provided information into a format suitable for use as the
214   * value of this extended request.
215   *
216   * @param  configurationType  The type of configuration that should be
217   *                            retrieved.
218   * @param  fileName           The name of the configuration file that should
219   *                            be retrieved, if appropriate.
220   *
221   * @return  The ASN.1 octet string containing the encoded representation of
222   *          the provided information.
223   */
224  @NotNull()
225  private static ASN1OctetString encodeValue(
226                      @NotNull final GetConfigurationType configurationType,
227                      @Nullable final String fileName)
228  {
229    final ArrayList<ASN1Element> elements = new ArrayList<>(0);
230    switch (configurationType)
231    {
232      case ACTIVE:
233        elements.add(new ASN1Null(configurationType.getBERType()));
234        break;
235
236      case BASELINE:
237      case ARCHIVED:
238        elements.add(
239             new ASN1OctetString(configurationType.getBERType(), fileName));
240        break;
241
242      default:
243        // This should never happen.
244        return null;
245    }
246
247    return new ASN1OctetString(new ASN1Sequence(elements).encode());
248  }
249
250
251
252  /**
253   * Creates a new get configuration extended request that may be used to
254   * retrieve the current active configuration.
255   *
256   * @param  controls  An optional set of controls to include in the request.
257   *                   This may be {@code null} or empty if no controls should
258   *                   be included in the request.
259   *
260   * @return  The get configuration extended request that has been created.
261   */
262  @NotNull()
263  public static GetConfigurationExtendedRequest
264                     createGetActiveConfigurationRequest(
265                          @Nullable final Control... controls)
266  {
267    return new GetConfigurationExtendedRequest(GetConfigurationType.ACTIVE,
268         null, controls);
269  }
270
271
272
273  /**
274   * Creates a new get configuration extended request that may be used to
275   * retrieve the baseline configuration for the current server version.
276   *
277   * @param  fileName  The name of the archived configuration file to retrieve.
278   *                   This must not be {@code null}.
279   * @param  controls  An optional set of controls to include in the request.
280   *                   This may be {@code null} or empty if no controls should
281   *                   be included in the request.
282   *
283   * @return  The get configuration extended request that has been created.
284   */
285  @NotNull()
286  public static GetConfigurationExtendedRequest
287                     createGetBaselineConfigurationRequest(
288                          @NotNull final String fileName,
289                          @Nullable final Control... controls)
290  {
291    Validator.ensureNotNull(fileName);
292
293    return new GetConfigurationExtendedRequest(GetConfigurationType.BASELINE,
294         fileName, controls);
295  }
296
297
298
299  /**
300   * Creates a new get configuration extended request that may be used to
301   * retrieve the baseline configuration for the current server version.
302   *
303   * @param  fileName  The name of the archived configuration file to retrieve.
304   *                   This must not be {@code null}.
305   * @param  controls  An optional set of controls to include in the request.
306   *                   This may be {@code null} or empty if no controls should
307   *                   be included in the request.
308   *
309   * @return  The get configuration extended request that has been created.
310   */
311  @NotNull()
312  public static GetConfigurationExtendedRequest
313                     createGetArchivedConfigurationRequest(
314                          @NotNull final String fileName,
315                          @Nullable final Control... controls)
316  {
317    Validator.ensureNotNull(fileName);
318
319    return new GetConfigurationExtendedRequest(GetConfigurationType.ARCHIVED,
320         fileName, controls);
321  }
322
323
324
325  /**
326   * Retrieves the type of configuration file that should be requested.
327   *
328   * @return  The type of configuration file that should be requested.
329   */
330  @NotNull()
331  public GetConfigurationType getConfigurationType()
332  {
333    return configurationType;
334  }
335
336
337
338  /**
339   * Retrieves the name of the configuration file that should be requested, if
340   * applicable.  This will only be available for requests that intend to
341   * retrieve a baseline or archived configuration.
342   *
343   * @return  The name of the configuration file that should be requested, or
344   *          {@code null} if this is not applicable.
345   */
346  @Nullable()
347  public String getFileName()
348  {
349    return fileName;
350  }
351
352
353
354  /**
355   * {@inheritDoc}
356   */
357  @Override()
358  @NotNull()
359  public GetConfigurationExtendedResult process(
360              @NotNull final LDAPConnection connection, final int depth)
361         throws LDAPException
362  {
363    final ExtendedResult extendedResponse = super.process(connection, depth);
364    return new GetConfigurationExtendedResult(extendedResponse);
365  }
366
367
368
369  /**
370   * {@inheritDoc}
371   */
372  @Override()
373  @NotNull()
374  public GetConfigurationExtendedRequest duplicate()
375  {
376    return duplicate(getControls());
377  }
378
379
380
381  /**
382   * {@inheritDoc}
383   */
384  @Override()
385  @NotNull()
386  public GetConfigurationExtendedRequest duplicate(
387              @Nullable final Control[] controls)
388  {
389    final GetConfigurationExtendedRequest r =
390         new GetConfigurationExtendedRequest(configurationType, fileName,
391              controls);
392    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
393    r.setIntermediateResponseListener(getIntermediateResponseListener());
394    r.setReferralDepth(getReferralDepth());
395    r.setReferralConnector(getReferralConnectorInternal());
396    return r;
397  }
398
399
400
401  /**
402   * {@inheritDoc}
403   */
404  @Override()
405  @NotNull()
406  public String getExtendedRequestName()
407  {
408    return INFO_EXTENDED_REQUEST_NAME_GET_CONFIG.get();
409  }
410
411
412
413  /**
414   * {@inheritDoc}
415   */
416  @Override()
417  public void toString(@NotNull final StringBuilder buffer)
418  {
419    buffer.append("GetConfigurationsExtendedRequest(configType=");
420    buffer.append(configurationType.name());
421
422    if (fileName != null)
423    {
424      buffer.append(", fileName='");
425      buffer.append(fileName);
426      buffer.append('\'');
427    }
428
429    final Control[] controls = getControls();
430    if (controls.length > 0)
431    {
432      buffer.append(", controls={");
433      for (int i=0; i < controls.length; i++)
434      {
435        if (i > 0)
436        {
437          buffer.append(", ");
438        }
439
440        buffer.append(controls[i]);
441      }
442      buffer.append('}');
443    }
444
445    buffer.append(')');
446  }
447}