001/*
002 * Copyright 2013-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-2020 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) 2015-2020 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 com.unboundid.asn1.ASN1Element;
041import com.unboundid.asn1.ASN1OctetString;
042import com.unboundid.asn1.ASN1Sequence;
043import com.unboundid.ldap.sdk.Control;
044import com.unboundid.ldap.sdk.ExtendedRequest;
045import com.unboundid.ldap.sdk.ExtendedResult;
046import com.unboundid.ldap.sdk.LDAPConnection;
047import com.unboundid.ldap.sdk.LDAPException;
048import com.unboundid.ldap.sdk.ResultCode;
049import com.unboundid.util.Debug;
050import com.unboundid.util.StaticUtils;
051import com.unboundid.util.ThreadSafety;
052import com.unboundid.util.ThreadSafetyLevel;
053import com.unboundid.util.Validator;
054
055import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
056
057
058
059/**
060 * This class provides an implementation of an extended request that can be used
061 * to identify potential incompatibility problems between two backup
062 * compatibility descriptor values.  This can be used to determine whether a
063 * backup from one server (or an older version of the same server) could be
064 * restored into another server (or a newer version of the same server).  It
065 * may also be useful in determining whether replication initialization via
066 * binary copy may be performed between two servers.
067 * <BR>
068 * <BLOCKQUOTE>
069 *   <B>NOTE:</B>  This class, and other classes within the
070 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
071 *   supported for use against Ping Identity, UnboundID, and
072 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
073 *   for proprietary functionality or for external specifications that are not
074 *   considered stable or mature enough to be guaranteed to work in an
075 *   interoperable way with other types of LDAP servers.
076 * </BLOCKQUOTE>
077 * <BR>
078 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.32.  It must have
079 * a value with the following encoding:
080 * <PRE>
081 *   IdentifyBackupCompatibilityProblemsRequest ::= SEQUENCE {
082 *        sourceDescriptor     [0] OCTET STRING,
083 *        targetDescriptor     [1] OCTET STRING,
084 *        ... }
085 * </PRE>
086 *
087 * @see  IdentifyBackupCompatibilityProblemsExtendedResult
088 * @see  GetBackupCompatibilityDescriptorExtendedRequest
089 */
090@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
091public final class IdentifyBackupCompatibilityProblemsExtendedRequest
092       extends ExtendedRequest
093{
094  /**
095   * The OID (1.3.6.1.4.1.30221.2.6.32) for the identify backup compatibility
096   * problems extended request.
097   */
098  public static final String
099       IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_REQUEST_OID =
100            "1.3.6.1.4.1.30221.2.6.32";
101
102
103
104  /**
105   * The BER type for the source descriptor element in the value sequence.
106   */
107  private static final byte TYPE_SOURCE_DESCRIPTOR = (byte) 0x80;
108
109
110
111  /**
112   * The BER type for the target descriptor element in the value sequence.
113   */
114  private static final byte TYPE_TARGET_DESCRIPTOR = (byte) 0x81;
115
116
117
118  /**
119   * The serial version UID for this serializable class.
120   */
121  private static final long serialVersionUID = 6723590129573376599L;
122
123
124
125  // The backup compatibility descriptor obtained from the source server, or
126  // from a backup to be restored.
127  private final ASN1OctetString sourceDescriptor;
128
129  // The backup compatibility descriptor obtained from the target server.
130  private final ASN1OctetString targetDescriptor;
131
132
133
134  /**
135   * Creates a new identify backup compatibility problems extended request with
136   * the provided information.
137   *
138   * @param  sourceDescriptor  The backup compatibility descriptor obtained from
139   *                           the source server, or from a backup to be
140   *                           restored.  It must not be {@code null}.
141   * @param  targetDescriptor  The backup compatibility descriptor obtained from
142   *                           the target server.  It must not be {@code null}.
143   * @param  controls          The set of controls to include in the request.
144   *                           It may be {@code null} or empty if no controls
145   *                           should be included.
146   */
147  public IdentifyBackupCompatibilityProblemsExtendedRequest(
148       final ASN1OctetString sourceDescriptor,
149       final ASN1OctetString targetDescriptor, final Control... controls)
150  {
151    super(IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_REQUEST_OID,
152         encodeValue(sourceDescriptor, targetDescriptor), controls);
153
154    this.sourceDescriptor = new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR,
155         sourceDescriptor.getValue());
156    this.targetDescriptor = new ASN1OctetString(TYPE_TARGET_DESCRIPTOR,
157         targetDescriptor.getValue());
158  }
159
160
161
162  /**
163   * Creates a new identify backup compatibility problems extended request from
164   * the provided generic extended request.
165   *
166   * @param  r  The generic extended request to decode as an identify backup
167   *            compatibility problems extended request.
168   *
169   * @throws LDAPException  If the provided request cannot be decoded as an
170   *                        identify backup compatibility problems extended
171   *                        request.
172   */
173  public IdentifyBackupCompatibilityProblemsExtendedRequest(
174       final ExtendedRequest r)
175       throws LDAPException
176  {
177    super(r);
178
179    final ASN1OctetString value = r.getValue();
180    if (value == null)
181    {
182      throw new LDAPException(ResultCode.DECODING_ERROR,
183           ERR_IDENTIFY_BACKUP_COMPAT_PROBLEMS_REQUEST_NO_VALUE.get());
184    }
185
186    try
187    {
188      final ASN1Element[] elements =
189           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
190      sourceDescriptor =
191           new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, elements[0].getValue());
192      targetDescriptor =
193           new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, elements[1].getValue());
194    }
195    catch (final Exception e)
196    {
197      Debug.debugException(e);
198      throw new LDAPException(ResultCode.DECODING_ERROR,
199           ERR_IDENTIFY_BACKUP_COMPAT_PROBLEMS_REQUEST_ERROR_PARSING_VALUE.get(
200                StaticUtils.getExceptionMessage(e)),
201           e);
202    }
203  }
204
205
206
207  /**
208   * Encodes the provided information into a format suitable for use as the
209   * value of this extended request.
210   *
211   * @param  sourceDescriptor  The backup compatibility descriptor obtained from
212   *                           the source server, or from a backup to be
213   *                           restored.  It must not be {@code null}.
214   * @param  targetDescriptor  The backup compatibility descriptor obtained from
215   *                           the target server.  It must not be {@code null}.
216   *
217   * @return  The ASN.1 octet string containing the encoded representation of
218   *          the provided information.
219   */
220  private static ASN1OctetString encodeValue(
221                                      final ASN1OctetString sourceDescriptor,
222                                      final ASN1OctetString targetDescriptor)
223  {
224    Validator.ensureNotNull(sourceDescriptor);
225    Validator.ensureNotNull(targetDescriptor);
226
227    final ASN1Sequence valueSequence = new ASN1Sequence(
228         new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR,
229              sourceDescriptor.getValue()),
230         new ASN1OctetString(TYPE_TARGET_DESCRIPTOR,
231              targetDescriptor.getValue()));
232
233    return new ASN1OctetString(valueSequence.encode());
234  }
235
236
237
238  /**
239   * Retrieves the backup compatibility descriptor obtained from the source
240   * server, or from a backup to be restored.
241   *
242   * @return  The backup compatibility descriptor obtained from the source
243   *          server, or from a backup to be restored.
244   */
245  public ASN1OctetString getSourceDescriptor()
246  {
247    return sourceDescriptor;
248  }
249
250
251
252  /**
253   * Retrieves the backup compatibility descriptor obtained from the target
254   * server.
255   *
256   * @return  The backup compatibility descriptor obtained from the target
257   *          server.
258   */
259  public ASN1OctetString getTargetDescriptor()
260  {
261    return targetDescriptor;
262  }
263
264
265
266  /**
267   * {@inheritDoc}
268   */
269  @Override()
270  public IdentifyBackupCompatibilityProblemsExtendedResult process(
271              final LDAPConnection connection, final int depth)
272         throws LDAPException
273  {
274    final ExtendedResult extendedResponse = super.process(connection, depth);
275    return new IdentifyBackupCompatibilityProblemsExtendedResult(
276         extendedResponse);
277  }
278
279
280
281  /**
282   * {@inheritDoc}
283   */
284  @Override()
285  public IdentifyBackupCompatibilityProblemsExtendedRequest duplicate()
286  {
287    return duplicate(getControls());
288  }
289
290
291
292  /**
293   * {@inheritDoc}
294   */
295  @Override()
296  public IdentifyBackupCompatibilityProblemsExtendedRequest duplicate(
297              final Control[] controls)
298  {
299    final IdentifyBackupCompatibilityProblemsExtendedRequest r =
300         new IdentifyBackupCompatibilityProblemsExtendedRequest(
301              sourceDescriptor, targetDescriptor, controls);
302    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
303    return r;
304  }
305
306
307
308  /**
309   * {@inheritDoc}
310   */
311  @Override()
312  public String getExtendedRequestName()
313  {
314    return INFO_EXTENDED_REQUEST_NAME_IDENTIFY_BACKUP_COMPAT_PROBLEMS.get();
315  }
316
317
318
319  /**
320   * {@inheritDoc}
321   */
322  @Override()
323  public void toString(final StringBuilder buffer)
324  {
325    buffer.append("IdentifyBackupCompatibilityProblemsExtendedRequest(" +
326         "sourceDescriptorLength=");
327    buffer.append(sourceDescriptor.getValueLength());
328    buffer.append(", targetDescriptorLength=");
329    buffer.append(targetDescriptor.getValueLength());
330
331    final Control[] controls = getControls();
332    if (controls.length > 0)
333    {
334      buffer.append(", controls={");
335      for (int i=0; i < controls.length; i++)
336      {
337        if (i > 0)
338        {
339          buffer.append(", ");
340        }
341
342        buffer.append(controls[i]);
343      }
344      buffer.append('}');
345    }
346
347    buffer.append(')');
348  }
349}