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 identify potential incompatibility problems between two backup
057 * compatibility descriptor values.
058 * <BR><BR>
059 * The OID for this extended result is 1.3.6.1.4.1.30221.2.6.33. If the request
060 * was processed successfully, then the response will have a value with the
061 * following encoding:
062 * <PRE>
063 * IdentifyBackupCompatibilityProblemsResult ::= SEQUENCE {
064 * errorMessages [0] SEQUENCE OF OCTET STRING OPTIONAL,
065 * warningMessages [1] SEQUENCE OF OCTET STRING OPTIONAL,
066 * ... }
067 * </PRE>
068 *
069 * @see IdentifyBackupCompatibilityProblemsExtendedRequest
070 * @see GetBackupCompatibilityDescriptorExtendedRequest
071 */
072 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
073 public final class IdentifyBackupCompatibilityProblemsExtendedResult
074 extends ExtendedResult
075 {
076 /**
077 * The OID (1.3.6.1.4.1.30221.2.6.33) for the identify backup compatibility
078 * problems extended request.
079 */
080 public static final String IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_RESULT_OID =
081 "1.3.6.1.4.1.30221.2.6.33";
082
083
084
085 /**
086 * The BER type for the error messages element in the value sequence.
087 */
088 private static final byte TYPE_ERRORS = (byte) 0xA0;
089
090
091
092 /**
093 * The BER type for the warning messages element in the value sequence.
094 */
095 private static final byte TYPE_WARNINGS = (byte) 0xA1;
096
097
098
099 /**
100 * The serial version UID for this serializable class.
101 */
102 private static final long serialVersionUID = -6492859100961846933L;
103
104
105
106 // The compatibility error messages.
107 private final List<String> errorMessages;
108
109 // The compatibility warning messages.
110 private final List<String> warningMessages;
111
112
113
114 /**
115 * Creates a new identify backup compatibility problems extended result from
116 * the provided generic extended result.
117 *
118 * @param result The generic extended result to be decoded as an identify
119 * backup compatibility problems extended result.
120 *
121 * @throws LDAPException If the provided extended result cannot be parsed as
122 * a valid identify backup compatibility problems
123 * extended result.
124 */
125 public IdentifyBackupCompatibilityProblemsExtendedResult(
126 final ExtendedResult result)
127 throws LDAPException
128 {
129 super(result);
130
131 final ASN1OctetString value = result.getValue();
132 if (value == null)
133 {
134 errorMessages = Collections.emptyList();
135 warningMessages = Collections.emptyList();
136 return;
137 }
138
139 try
140 {
141 List<String> errors = Collections.emptyList();
142 List<String> warnings = Collections.emptyList();
143 final ASN1Element[] elements =
144 ASN1Sequence.decodeAsSequence(value.getValue()).elements();
145 for (final ASN1Element e : elements)
146 {
147 switch (e.getType())
148 {
149 case TYPE_ERRORS:
150 final ASN1Element[] errorElements =
151 ASN1Sequence.decodeAsSequence(e).elements();
152 final ArrayList<String> errorStrings =
153 new ArrayList<String>(errorElements.length);
154 for (final ASN1Element errorElement : errorElements)
155 {
156 errorStrings.add(ASN1OctetString.decodeAsOctetString(
157 errorElement).stringValue());
158 }
159 errors = Collections.unmodifiableList(errorStrings);
160 break;
161
162 case TYPE_WARNINGS:
163 final ASN1Element[] warningElements =
164 ASN1Sequence.decodeAsSequence(e).elements();
165 final ArrayList<String> warningStrings =
166 new ArrayList<String>(warningElements.length);
167 for (final ASN1Element warningElement : warningElements)
168 {
169 warningStrings.add(ASN1OctetString.decodeAsOctetString(
170 warningElement).stringValue());
171 }
172 warnings = Collections.unmodifiableList(warningStrings);
173 break;
174
175 default:
176 throw new LDAPException(ResultCode.DECODING_ERROR,
177 ERR_IDENTIFY_BACKUP_COMPAT_PROBLEMS_RESULT_UNEXPECTED_TYPE.get(
178 StaticUtils.toHex(e.getType())));
179 }
180 }
181
182 errorMessages = errors;
183 warningMessages = warnings;
184 }
185 catch (final LDAPException le)
186 {
187 Debug.debugException(le);
188 throw le;
189 }
190 catch (final Exception e)
191 {
192 Debug.debugException(e);
193 throw new LDAPException(ResultCode.DECODING_ERROR,
194 ERR_GET_BACKUP_COMPAT_RESULT_ERROR_PARSING_VALUE.get(
195 StaticUtils.getExceptionMessage(e)),
196 e);
197 }
198 }
199
200
201
202 /**
203 * Creates a new identify backup compatibility problems extended result with
204 * the provided information.
205 *
206 * @param messageID The message ID for the LDAP message that is
207 * associated with this LDAP result.
208 * @param resultCode The result code from the response.
209 * @param diagnosticMessage The diagnostic message from the response, if
210 * available.
211 * @param matchedDN The matched DN from the response, if available.
212 * @param referralURLs The set of referral URLs from the response, if
213 * available.
214 * @param errorMessages The set of error messages to include in the
215 * result. It may be {@code null} or empty if no
216 * error messages should be included.
217 * @param warningMessages The set of warning messages to include in the
218 * result. It may be {@code null} or empty if no
219 * warning messages should be included.
220 * @param responseControls The set of controls from the response, if
221 * available.
222 */
223 public IdentifyBackupCompatibilityProblemsExtendedResult(final int messageID,
224 final ResultCode resultCode, final String diagnosticMessage,
225 final String matchedDN, final String[] referralURLs,
226 final Collection<String> errorMessages,
227 final Collection<String> warningMessages,
228 final Control... responseControls)
229 {
230 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
231 ((resultCode == ResultCode.SUCCESS)
232 ? IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_RESULT_OID
233 : null),
234 encodeValue(resultCode, errorMessages, warningMessages),
235 responseControls);
236
237 if (errorMessages == null)
238 {
239 this.errorMessages = Collections.emptyList();
240 }
241 else
242 {
243 this.errorMessages =
244 Collections.unmodifiableList(new ArrayList<String>(errorMessages));
245 }
246
247 if (warningMessages == null)
248 {
249 this.warningMessages = Collections.emptyList();
250 }
251 else
252 {
253 this.warningMessages =
254 Collections.unmodifiableList(new ArrayList<String>(warningMessages));
255 }
256 }
257
258
259
260 /**
261 * Creates an ASN.1 octet string containing an encoded representation of the
262 * value for an identify backup compatibility problems extended result with
263 * the provided information.
264 *
265 * @param resultCode The result code from the response.
266 * @param errorMessages The set of error messages to include in the
267 * result. It may be {@code null} or empty if no
268 * error messages should be included.
269 * @param warningMessages The set of warning messages to include in the
270 * result. It may be {@code null} or empty if no
271 * warning messages should be included.
272 *
273 * @return An ASN.1 octet string containing an encoded representation of the
274 * value for an identify backup compatibility problems extended
275 * result, or {@code null} if a result with the provided information
276 * should not have a value.
277 */
278 public static ASN1OctetString encodeValue(final ResultCode resultCode,
279 final Collection<String> errorMessages,
280 final Collection<String> warningMessages)
281 {
282 if (resultCode != ResultCode.SUCCESS)
283 {
284 Validator.ensureTrue(
285 (((errorMessages == null) || errorMessages.isEmpty()) &&
286 ((warningMessages == null) || warningMessages.isEmpty())),
287 "There must not be any warning or error messages with a " +
288 "non-success result.");
289 return null;
290 }
291
292 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
293
294 if ((errorMessages != null) && (! errorMessages.isEmpty()))
295 {
296 final ArrayList<ASN1Element> msgElements =
297 new ArrayList<ASN1Element>(errorMessages.size());
298 for (final String s : errorMessages)
299 {
300 msgElements.add(new ASN1OctetString(s));
301 }
302 elements.add(new ASN1Sequence(TYPE_ERRORS, msgElements));
303 }
304
305 if ((warningMessages != null) && (! warningMessages.isEmpty()))
306 {
307 final ArrayList<ASN1Element> msgElements =
308 new ArrayList<ASN1Element>(warningMessages.size());
309 for (final String s : warningMessages)
310 {
311 msgElements.add(new ASN1OctetString(s));
312 }
313 elements.add(new ASN1Sequence(TYPE_WARNINGS, msgElements));
314 }
315
316 return new ASN1OctetString(new ASN1Sequence(elements).encode());
317 }
318
319
320
321 /**
322 * Retrieves a list of messages for any compatibility errors that have been
323 * identified. If there are any errors, a backup from the source cannot be
324 * restored into the target.
325 *
326 * @return A list of messages for any compatibility errors that have been
327 * identified, or an empty list if there are no compatibility errors.
328 */
329 public List<String> getErrorMessages()
330 {
331 return errorMessages;
332 }
333
334
335
336 /**
337 * Retrieves a list of messages for any compatibility warnings that have been
338 * identified. If there are any warnings, it may still be possible to restore
339 * a backup from the source into the target.
340 *
341 * @return A list of messages for any compatibility warnings that have been
342 * identified, or an empty list if there are no compatibility
343 * warnings.
344 */
345 public List<String> getWarningMessages()
346 {
347 return warningMessages;
348 }
349
350
351
352 /**
353 * {@inheritDoc}
354 */
355 @Override()
356 public String getExtendedResultName()
357 {
358 return INFO_EXTENDED_RESULT_NAME_IDENTIFY_BACKUP_COMPAT_PROBLEMS.get();
359 }
360
361
362
363 /**
364 * {@inheritDoc}
365 */
366 @Override()
367 public void toString(final StringBuilder buffer)
368 {
369 buffer.append("IdentifyBackupCompatibilityProblemsExtendedResult(" +
370 "resultCode=");
371 buffer.append(getResultCode());
372
373 final int messageID = getMessageID();
374 if (messageID >= 0)
375 {
376 buffer.append(", messageID=");
377 buffer.append(messageID);
378 }
379
380 if (! errorMessages.isEmpty())
381 {
382 buffer.append(", errorMessages={");
383
384 final Iterator<String> iterator = errorMessages.iterator();
385 while (iterator.hasNext())
386 {
387 buffer.append('\'');
388 buffer.append(iterator.next());
389 buffer.append('\'');
390
391 if (iterator.hasNext())
392 {
393 buffer.append(',');
394 }
395 }
396
397 buffer.append('}');
398 }
399
400 if (! warningMessages.isEmpty())
401 {
402 buffer.append(", warningMessages={");
403
404 final Iterator<String> iterator = warningMessages.iterator();
405 while (iterator.hasNext())
406 {
407 buffer.append('\'');
408 buffer.append(iterator.next());
409 buffer.append('\'');
410
411 if (iterator.hasNext())
412 {
413 buffer.append(',');
414 }
415 }
416
417 buffer.append('}');
418 }
419
420 final String diagnosticMessage = getDiagnosticMessage();
421 if (diagnosticMessage != null)
422 {
423 buffer.append(", diagnosticMessage='");
424 buffer.append(diagnosticMessage);
425 buffer.append('\'');
426 }
427
428 final String matchedDN = getMatchedDN();
429 if (matchedDN != null)
430 {
431 buffer.append(", matchedDN='");
432 buffer.append(matchedDN);
433 buffer.append('\'');
434 }
435
436 final String[] referralURLs = getReferralURLs();
437 if (referralURLs.length > 0)
438 {
439 buffer.append(", referralURLs={");
440 for (int i=0; i < referralURLs.length; i++)
441 {
442 if (i > 0)
443 {
444 buffer.append(", ");
445 }
446
447 buffer.append('\'');
448 buffer.append(referralURLs[i]);
449 buffer.append('\'');
450 }
451 buffer.append('}');
452 }
453
454 final Control[] responseControls = getResponseControls();
455 if (responseControls.length > 0)
456 {
457 buffer.append(", responseControls={");
458 for (int i=0; i < responseControls.length; i++)
459 {
460 if (i > 0)
461 {
462 buffer.append(", ");
463 }
464
465 buffer.append(responseControls[i]);
466 }
467 buffer.append('}');
468 }
469
470 buffer.append(')');
471 }
472 }