001/* 002 * Copyright 2013-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 Ping Identity Corporation 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 */ 021package com.unboundid.ldap.sdk.unboundidds.extensions; 022 023 024 025import com.unboundid.asn1.ASN1Element; 026import com.unboundid.asn1.ASN1OctetString; 027import com.unboundid.asn1.ASN1Sequence; 028import com.unboundid.ldap.sdk.Control; 029import com.unboundid.ldap.sdk.ExtendedRequest; 030import com.unboundid.ldap.sdk.ExtendedResult; 031import com.unboundid.ldap.sdk.LDAPConnection; 032import com.unboundid.ldap.sdk.LDAPException; 033import com.unboundid.ldap.sdk.ResultCode; 034import com.unboundid.util.Debug; 035import com.unboundid.util.StaticUtils; 036import com.unboundid.util.ThreadSafety; 037import com.unboundid.util.ThreadSafetyLevel; 038import com.unboundid.util.Validator; 039 040import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 041 042 043 044/** 045 * This class provides an implementation of an extended request that can be used 046 * to identify potential incompatibility problems between two backup 047 * compatibility descriptor values. This can be used to determine whether a 048 * backup from one server (or an older version of the same server) could be 049 * restored into another server (or a newer version of the same server). It 050 * may also be useful in determining whether replication initialization via 051 * binary copy may be performed between two servers. 052 * <BR> 053 * <BLOCKQUOTE> 054 * <B>NOTE:</B> This class, and other classes within the 055 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 056 * supported for use against Ping Identity, UnboundID, and 057 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 058 * for proprietary functionality or for external specifications that are not 059 * considered stable or mature enough to be guaranteed to work in an 060 * interoperable way with other types of LDAP servers. 061 * </BLOCKQUOTE> 062 * <BR> 063 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.32. It must have 064 * a value with the following encoding: 065 * <PRE> 066 * IdentifyBackupCompatibilityProblemsRequest ::= SEQUENCE { 067 * sourceDescriptor [0] OCTET STRING, 068 * targetDescriptor [1] OCTET STRING, 069 * ... } 070 * </PRE> 071 * 072 * @see IdentifyBackupCompatibilityProblemsExtendedResult 073 * @see GetBackupCompatibilityDescriptorExtendedRequest 074 */ 075@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 076public final class IdentifyBackupCompatibilityProblemsExtendedRequest 077 extends ExtendedRequest 078{ 079 /** 080 * The OID (1.3.6.1.4.1.30221.2.6.32) for the identify backup compatibility 081 * problems extended request. 082 */ 083 public static final String 084 IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_REQUEST_OID = 085 "1.3.6.1.4.1.30221.2.6.32"; 086 087 088 089 /** 090 * The BER type for the source descriptor element in the value sequence. 091 */ 092 private static final byte TYPE_SOURCE_DESCRIPTOR = (byte) 0x80; 093 094 095 096 /** 097 * The BER type for the target descriptor element in the value sequence. 098 */ 099 private static final byte TYPE_TARGET_DESCRIPTOR = (byte) 0x81; 100 101 102 103 /** 104 * The serial version UID for this serializable class. 105 */ 106 private static final long serialVersionUID = 6723590129573376599L; 107 108 109 110 // The backup compatibility descriptor obtained from the source server, or 111 // from a backup to be restored. 112 private final ASN1OctetString sourceDescriptor; 113 114 // The backup compatibility descriptor obtained from the target server. 115 private final ASN1OctetString targetDescriptor; 116 117 118 119 /** 120 * Creates a new identify backup compatibility problems extended request with 121 * the provided information. 122 * 123 * @param sourceDescriptor The backup compatibility descriptor obtained from 124 * the source server, or from a backup to be 125 * restored. It must not be {@code null}. 126 * @param targetDescriptor The backup compatibility descriptor obtained from 127 * the target server. It must not be {@code null}. 128 * @param controls The set of controls to include in the request. 129 * It may be {@code null} or empty if no controls 130 * should be included. 131 */ 132 public IdentifyBackupCompatibilityProblemsExtendedRequest( 133 final ASN1OctetString sourceDescriptor, 134 final ASN1OctetString targetDescriptor, final Control... controls) 135 { 136 super(IDENTIFY_BACKUP_COMPATIBILITY_PROBLEMS_REQUEST_OID, 137 encodeValue(sourceDescriptor, targetDescriptor), controls); 138 139 this.sourceDescriptor = new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, 140 sourceDescriptor.getValue()); 141 this.targetDescriptor = new ASN1OctetString(TYPE_TARGET_DESCRIPTOR, 142 targetDescriptor.getValue()); 143 } 144 145 146 147 /** 148 * Creates a new identify backup compatibility problems extended request from 149 * the provided generic extended request. 150 * 151 * @param r The generic extended request to decode as an identify backup 152 * compatibility problems extended request. 153 * 154 * @throws LDAPException If the provided request cannot be decoded as an 155 * identify backup compatibility problems extended 156 * request. 157 */ 158 public IdentifyBackupCompatibilityProblemsExtendedRequest( 159 final ExtendedRequest r) 160 throws LDAPException 161 { 162 super(r); 163 164 final ASN1OctetString value = r.getValue(); 165 if (value == null) 166 { 167 throw new LDAPException(ResultCode.DECODING_ERROR, 168 ERR_IDENTIFY_BACKUP_COMPAT_PROBLEMS_REQUEST_NO_VALUE.get()); 169 } 170 171 try 172 { 173 final ASN1Element[] elements = 174 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 175 sourceDescriptor = 176 new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, elements[0].getValue()); 177 targetDescriptor = 178 new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, elements[1].getValue()); 179 } 180 catch (final Exception e) 181 { 182 Debug.debugException(e); 183 throw new LDAPException(ResultCode.DECODING_ERROR, 184 ERR_IDENTIFY_BACKUP_COMPAT_PROBLEMS_REQUEST_ERROR_PARSING_VALUE.get( 185 StaticUtils.getExceptionMessage(e)), 186 e); 187 } 188 } 189 190 191 192 /** 193 * Encodes the provided information into a format suitable for use as the 194 * value of this extended request. 195 * 196 * @param sourceDescriptor The backup compatibility descriptor obtained from 197 * the source server, or from a backup to be 198 * restored. It must not be {@code null}. 199 * @param targetDescriptor The backup compatibility descriptor obtained from 200 * the target server. It must not be {@code null}. 201 * 202 * @return The ASN.1 octet string containing the encoded representation of 203 * the provided information. 204 */ 205 private static ASN1OctetString encodeValue( 206 final ASN1OctetString sourceDescriptor, 207 final ASN1OctetString targetDescriptor) 208 { 209 Validator.ensureNotNull(sourceDescriptor); 210 Validator.ensureNotNull(targetDescriptor); 211 212 final ASN1Sequence valueSequence = new ASN1Sequence( 213 new ASN1OctetString(TYPE_SOURCE_DESCRIPTOR, 214 sourceDescriptor.getValue()), 215 new ASN1OctetString(TYPE_TARGET_DESCRIPTOR, 216 targetDescriptor.getValue())); 217 218 return new ASN1OctetString(valueSequence.encode()); 219 } 220 221 222 223 /** 224 * Retrieves the backup compatibility descriptor obtained from the source 225 * server, or from a backup to be restored. 226 * 227 * @return The backup compatibility descriptor obtained from the source 228 * server, or from a backup to be restored. 229 */ 230 public ASN1OctetString getSourceDescriptor() 231 { 232 return sourceDescriptor; 233 } 234 235 236 237 /** 238 * Retrieves the backup compatibility descriptor obtained from the target 239 * server. 240 * 241 * @return The backup compatibility descriptor obtained from the target 242 * server. 243 */ 244 public ASN1OctetString getTargetDescriptor() 245 { 246 return targetDescriptor; 247 } 248 249 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override() 255 public IdentifyBackupCompatibilityProblemsExtendedResult process( 256 final LDAPConnection connection, final int depth) 257 throws LDAPException 258 { 259 final ExtendedResult extendedResponse = super.process(connection, depth); 260 return new IdentifyBackupCompatibilityProblemsExtendedResult( 261 extendedResponse); 262 } 263 264 265 266 /** 267 * {@inheritDoc} 268 */ 269 @Override() 270 public IdentifyBackupCompatibilityProblemsExtendedRequest duplicate() 271 { 272 return duplicate(getControls()); 273 } 274 275 276 277 /** 278 * {@inheritDoc} 279 */ 280 @Override() 281 public IdentifyBackupCompatibilityProblemsExtendedRequest duplicate( 282 final Control[] controls) 283 { 284 final IdentifyBackupCompatibilityProblemsExtendedRequest r = 285 new IdentifyBackupCompatibilityProblemsExtendedRequest( 286 sourceDescriptor, targetDescriptor, controls); 287 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 288 return r; 289 } 290 291 292 293 /** 294 * {@inheritDoc} 295 */ 296 @Override() 297 public String getExtendedRequestName() 298 { 299 return INFO_EXTENDED_REQUEST_NAME_IDENTIFY_BACKUP_COMPAT_PROBLEMS.get(); 300 } 301 302 303 304 /** 305 * {@inheritDoc} 306 */ 307 @Override() 308 public void toString(final StringBuilder buffer) 309 { 310 buffer.append("IdentifyBackupCompatibilityProblemsExtendedRequest(" + 311 "sourceDescriptorLength="); 312 buffer.append(sourceDescriptor.getValueLength()); 313 buffer.append(", targetDescriptorLength="); 314 buffer.append(targetDescriptor.getValueLength()); 315 316 final Control[] controls = getControls(); 317 if (controls.length > 0) 318 { 319 buffer.append(", controls={"); 320 for (int i=0; i < controls.length; i++) 321 { 322 if (i > 0) 323 { 324 buffer.append(", "); 325 } 326 327 buffer.append(controls[i]); 328 } 329 buffer.append('}'); 330 } 331 332 buffer.append(')'); 333 } 334}