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 java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.Iterator;
029    import java.util.List;
030    
031    import com.unboundid.asn1.ASN1Element;
032    import com.unboundid.asn1.ASN1OctetString;
033    import com.unboundid.asn1.ASN1Sequence;
034    import com.unboundid.ldap.sdk.Control;
035    import com.unboundid.ldap.sdk.ExtendedResult;
036    import com.unboundid.ldap.sdk.LDAPException;
037    import com.unboundid.ldap.sdk.ResultCode;
038    import com.unboundid.util.Debug;
039    import com.unboundid.util.StaticUtils;
040    import com.unboundid.util.ThreadSafety;
041    import com.unboundid.util.ThreadSafetyLevel;
042    import com.unboundid.util.Validator;
043    
044    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
045    
046    
047    
048    /**
049     * <BLOCKQUOTE>
050     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
051     *   LDAP SDK for Java.  It is not available for use in applications that
052     *   include only the Standard Edition of the LDAP SDK, and is not supported for
053     *   use in conjunction with non-UnboundID products.
054     * </BLOCKQUOTE>
055     * This class provides an implementation of an extended result that can be used
056     * to retrieve backup compatibility data for a Directory Server backend.
057     * <BR><BR>
058     * The OID for this extended result is 1.3.6.1.4.1.30221.2.6.31.  If the request
059     * was processed successfully, then the response will have a value with the
060     * following encoding:
061     * <PRE>
062     *   GetBackupCompatibilityDescriptorResult ::= SEQUENCE {
063     *        descriptor     [0] OCTET STRING,
064     *        properties     [1] SEQUENCE OF OCTET STRING OPTIONAL,
065     *        ... }
066     * </PRE>
067     *
068     * @see  GetBackupCompatibilityDescriptorExtendedRequest
069     * @see  IdentifyBackupCompatibilityProblemsExtendedRequest
070     */
071    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
072    public final class GetBackupCompatibilityDescriptorExtendedResult
073           extends ExtendedResult
074    {
075      /**
076       * The OID (1.3.6.1.4.1.30221.2.6.31) for the get backup compatibility
077       * descriptor extended result.
078       */
079      public static final String GET_BACKUP_COMPATIBILITY_DESCRIPTOR_RESULT_OID =
080           "1.3.6.1.4.1.30221.2.6.31";
081    
082    
083    
084      /**
085       * The BER type for the descriptor element in the value sequence.
086       */
087      private static final byte TYPE_DESCRIPTOR = (byte) 0x80;
088    
089    
090    
091      /**
092       * The BER type for the properties element in the value sequence.
093       */
094      private static final byte TYPE_PROPERTIES = (byte) 0xA1;
095    
096    
097    
098      /**
099       * The serial version UID for this serializable class.
100       */
101      private static final long serialVersionUID = -2493658329210480765L;
102    
103    
104    
105      // The backup compatibility descriptor token.
106      private final ASN1OctetString descriptor;
107    
108      // A list of properties providing information about the backup compatibility
109      // descriptor.
110      private final List<String> properties;
111    
112    
113    
114      /**
115       * Creates a new get backup compatibility descriptor extended result from the
116       * provided generic extended result.
117       *
118       * @param  result  The generic extended result to be decoded as a get backup
119       *                 compatibility descriptor extended result.
120       *
121       * @throws LDAPException  If the provided extended result cannot be parsed as
122       *                        a valid get backup compatibility descriptor
123       *                        extended result.
124       */
125      public GetBackupCompatibilityDescriptorExtendedResult(
126           final ExtendedResult result)
127           throws LDAPException
128      {
129        super(result);
130    
131        final ASN1OctetString value = result.getValue();
132        if (value == null)
133        {
134          descriptor = null;
135          properties = Collections.emptyList();
136          return;
137        }
138    
139        try
140        {
141          final ASN1Element[] elements =
142               ASN1Sequence.decodeAsSequence(value.getValue()).elements();
143          descriptor = elements[0].decodeAsOctetString();
144    
145          if (elements.length > 1)
146          {
147            final ASN1Element[] propElements =
148                 ASN1Sequence.decodeAsSequence(elements[1]).elements();
149            final ArrayList<String> propList =
150                 new ArrayList<String>(propElements.length);
151            for (final ASN1Element e : propElements)
152            {
153              propList.add(ASN1OctetString.decodeAsOctetString(e).stringValue());
154            }
155            properties = Collections.unmodifiableList(propList);
156          }
157          else
158          {
159            properties = Collections.emptyList();
160          }
161        }
162        catch (final Exception e)
163        {
164          Debug.debugException(e);
165          throw new LDAPException(ResultCode.DECODING_ERROR,
166               ERR_GET_BACKUP_COMPAT_RESULT_ERROR_PARSING_VALUE.get(
167                    StaticUtils.getExceptionMessage(e)),
168               e);
169        }
170      }
171    
172    
173    
174      /**
175       * Creates a new get backup compatibility descriptor extended result with the
176       * provided information.
177       *
178       * @param  messageID          The message ID for the LDAP message that is
179       *                            associated with this LDAP result.
180       * @param  resultCode         The result code from the response.
181       * @param  diagnosticMessage  The diagnostic message from the response, if
182       *                            available.
183       * @param  matchedDN          The matched DN from the response, if available.
184       * @param  referralURLs       The set of referral URLs from the response, if
185       *                            available.
186       * @param  descriptor         The backup compatibility descriptor value.  It
187       *                            may be {@code null} for an unsuccessful result.
188       * @param  properties         A list of properties that provide information
189       *                            about the way the descriptor may be used.  It
190       *                            may be {@code null} or empty for an unsuccessful
191       *                            result, or if there are no properties.
192       * @param  responseControls   The set of controls from the response, if
193       *                            available.
194       */
195      public GetBackupCompatibilityDescriptorExtendedResult(final int messageID,
196                  final ResultCode resultCode, final String diagnosticMessage,
197                  final String matchedDN, final String[] referralURLs,
198                  final ASN1OctetString descriptor,
199                  final Collection<String> properties,
200                  final Control... responseControls)
201      {
202        super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
203             ((descriptor == null) ? null :
204                  GET_BACKUP_COMPATIBILITY_DESCRIPTOR_RESULT_OID),
205             encodeValue(descriptor, properties), responseControls);
206    
207        if (descriptor == null)
208        {
209          this.descriptor = null;
210        }
211        else
212        {
213          this.descriptor =
214               new ASN1OctetString(TYPE_DESCRIPTOR, descriptor.getValue());
215        }
216    
217        if (properties == null)
218        {
219          this.properties = Collections.emptyList();
220        }
221        else
222        {
223          this.properties =
224               Collections.unmodifiableList(new ArrayList<String>(properties));
225        }
226      }
227    
228    
229    
230      /**
231       * Creates an ASN.1 octet string containing an encoded representation of the
232       * value for a get backup compatibility descriptor extended result with the
233       * provided information.
234       *
235       * @param  descriptor  The backup compatibility descriptor value.  It may be
236       *                     {@code null} for an unsuccessful result.
237       * @param  properties  A list of properties that provide information about the
238       *                     way the descriptor may be used.  It may be {@code null}
239       *                     or empty for an unsuccessful result, or if there are no
240       *                     properties.
241       *
242       * @return  An ASN.1 octet string containing an encoded representation of the
243       *          value for a get backup compatibility descriptor extended result,
244       *          or {@code null} if a result with the provided information should
245       *          not have a value.
246       */
247      public static ASN1OctetString encodeValue(final ASN1OctetString descriptor,
248                                                final Collection<String> properties)
249      {
250        if (descriptor == null)
251        {
252          Validator.ensureTrue(((properties == null) || properties.isEmpty()),
253               "The properties must be null or empty if the descriptor is null.");
254          return null;
255        }
256    
257        final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
258        elements.add(new ASN1OctetString(TYPE_DESCRIPTOR, descriptor.getValue()));
259    
260        if ((properties != null) && (! properties.isEmpty()))
261        {
262          final ArrayList<ASN1Element> propElements =
263               new ArrayList<ASN1Element>(properties.size());
264          for (final String property : properties)
265          {
266            propElements.add(new ASN1OctetString(property));
267          }
268          elements.add(new ASN1Sequence(TYPE_PROPERTIES, propElements));
269        }
270    
271        return new ASN1OctetString(new ASN1Sequence(elements).encode());
272      }
273    
274    
275    
276      /**
277       * Retrieves the backup compatibility descriptor value, if available.
278       *
279       * @return  The backup compatibility descriptor value, or {@code null} if none
280       *          was provided.
281       */
282      public ASN1OctetString getDescriptor()
283      {
284        return descriptor;
285      }
286    
287    
288    
289      /**
290       * Retrieves a list of properties that provide information about the way the
291       * descriptor may be used.
292       *
293       * @return  A list of properties that provide information about the way the
294       *          descriptor may be used, or an empty list if no properties were
295       *          provided.
296       */
297      public List<String> getProperties()
298      {
299        return properties;
300      }
301    
302    
303    
304      /**
305       * {@inheritDoc}
306       */
307      @Override()
308      public String getExtendedResultName()
309      {
310        return INFO_EXTENDED_RESULT_NAME_GET_BACKUP_COMPAT.get();
311      }
312    
313    
314    
315      /**
316       * {@inheritDoc}
317       */
318      @Override()
319      public void toString(final StringBuilder buffer)
320      {
321        buffer.append("GetBackupCompatibilityDescriptorExtendedResult(resultCode=");
322        buffer.append(getResultCode());
323    
324        final int messageID = getMessageID();
325        if (messageID >= 0)
326        {
327          buffer.append(", messageID=");
328          buffer.append(messageID);
329        }
330    
331        if (descriptor != null)
332        {
333          buffer.append(", descriptorLength=");
334          buffer.append(descriptor.getValueLength());
335        }
336    
337        if (! properties.isEmpty())
338        {
339          buffer.append(", descriptorProperties={");
340    
341          final Iterator<String> iterator = properties.iterator();
342          while (iterator.hasNext())
343          {
344            buffer.append('\'');
345            buffer.append(iterator.next());
346            buffer.append('\'');
347    
348            if (iterator.hasNext())
349            {
350              buffer.append(',');
351            }
352          }
353    
354          buffer.append('}');
355        }
356    
357        final String diagnosticMessage = getDiagnosticMessage();
358        if (diagnosticMessage != null)
359        {
360          buffer.append(", diagnosticMessage='");
361          buffer.append(diagnosticMessage);
362          buffer.append('\'');
363        }
364    
365        final String matchedDN = getMatchedDN();
366        if (matchedDN != null)
367        {
368          buffer.append(", matchedDN='");
369          buffer.append(matchedDN);
370          buffer.append('\'');
371        }
372    
373        final String[] referralURLs = getReferralURLs();
374        if (referralURLs.length > 0)
375        {
376          buffer.append(", referralURLs={");
377          for (int i=0; i < referralURLs.length; i++)
378          {
379            if (i > 0)
380            {
381              buffer.append(", ");
382            }
383    
384            buffer.append('\'');
385            buffer.append(referralURLs[i]);
386            buffer.append('\'');
387          }
388          buffer.append('}');
389        }
390    
391        final Control[] responseControls = getResponseControls();
392        if (responseControls.length > 0)
393        {
394          buffer.append(", responseControls={");
395          for (int i=0; i < responseControls.length; i++)
396          {
397            if (i > 0)
398            {
399              buffer.append(", ");
400            }
401    
402            buffer.append(responseControls[i]);
403          }
404          buffer.append('}');
405        }
406    
407        buffer.append(')');
408      }
409    }