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