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 }