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 }