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 }