001/* 002 * Copyright 2012-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.controls; 022 023 024 025import com.unboundid.asn1.ASN1Boolean; 026import com.unboundid.asn1.ASN1Element; 027import com.unboundid.asn1.ASN1Integer; 028import com.unboundid.asn1.ASN1OctetString; 029import com.unboundid.asn1.ASN1Sequence; 030import com.unboundid.ldap.sdk.Control; 031import com.unboundid.ldap.sdk.DecodeableControl; 032import com.unboundid.ldap.sdk.ExtendedResult; 033import com.unboundid.ldap.sdk.LDAPException; 034import com.unboundid.ldap.sdk.ResultCode; 035import com.unboundid.util.Debug; 036import com.unboundid.util.NotMutable; 037import com.unboundid.util.StaticUtils; 038import com.unboundid.util.ThreadSafety; 039import com.unboundid.util.ThreadSafetyLevel; 040 041import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 042 043 044 045/** 046 * This class provides a response control that may be used to provide the 047 * client with information about transaction-related information over the 048 * course of the associated operation. 049 * <BR> 050 * <BLOCKQUOTE> 051 * <B>NOTE:</B> This class, and other classes within the 052 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 053 * supported for use against Ping Identity, UnboundID, and 054 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 055 * for proprietary functionality or for external specifications that are not 056 * considered stable or mature enough to be guaranteed to work in an 057 * interoperable way with other types of LDAP servers. 058 * </BLOCKQUOTE> 059 * <BR> 060 * This control has an OID of 1.3.6.1.4.1.30221.2.5.39. It should have a 061 * criticality of {@code false}, and a value with the following encoding: 062 * <PRE> 063 * TransactionSettingsResponseValue ::= SEQUENCE { 064 * numLockConflicts [0] INTEGER 065 * backendLockAcquired [1] BOOLEAN, 066 * ... } 067 * </PRE> 068 */ 069@NotMutable() 070@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 071public final class TransactionSettingsResponseControl 072 extends Control 073 implements DecodeableControl 074{ 075 /** 076 * The OID (1.3.6.1.4.1.30221.2.5.39) for the transaction settings response 077 * control. 078 */ 079 public static final String TRANSACTION_SETTINGS_RESPONSE_OID = 080 "1.3.6.1.4.1.30221.2.5.39"; 081 082 083 084 /** 085 * The BER type for the value element used to hold the number of lock 086 * conflicts encountered during the course of processing. 087 */ 088 private static final byte TYPE_NUM_LOCK_CONFLICTS = (byte) 0x80; 089 090 091 092 /** 093 * The BER type for the value element used to hold the number of lock 094 * conflicts encountered during the course of processing. 095 */ 096 private static final byte TYPE_BACKEND_LOCK_ACQUIRED = (byte) 0x81; 097 098 099 100 /** 101 * The serial version UID for this serializable class. 102 */ 103 private static final long serialVersionUID = 7290122856855738454L; 104 105 106 107 // Indicates whether the exclusive backend lock was acquired at any point 108 // during the course of processing the operation. 109 private final boolean backendLockAcquired; 110 111 // The number of lock conflicts encountered during the course of processing 112 // the operation. 113 private final int numLockConflicts; 114 115 116 117 /** 118 * Creates a new empty control instance that is intended to be used only for 119 * decoding controls via the {@code DecodeableControl} interface. 120 */ 121 TransactionSettingsResponseControl() 122 { 123 backendLockAcquired = false; 124 numLockConflicts = -1; 125 } 126 127 128 129 /** 130 * Creates a new transaction settings response control with the provided 131 * information. 132 * 133 * @param numLockConflicts The number of lock conflicts encountered 134 * during the course of processing the operation. 135 * @param backendLockAcquired Indicates whether the exclusive backend lock 136 * was acquired at any point during the course of 137 * processing the operation. 138 */ 139 public TransactionSettingsResponseControl(final int numLockConflicts, 140 final boolean backendLockAcquired) 141 { 142 super(TRANSACTION_SETTINGS_RESPONSE_OID, false, 143 encodeValue(numLockConflicts, backendLockAcquired)); 144 145 this.numLockConflicts = numLockConflicts; 146 this.backendLockAcquired = backendLockAcquired; 147 } 148 149 150 151 /** 152 * Creates a new transaction settings response control with the provided 153 * information. 154 * 155 * @param oid The OID for the control. 156 * @param isCritical Indicates whether the control should be considered 157 * critical. 158 * @param value The value for the control. 159 * 160 * @throws LDAPException If the provided information cannot be used to 161 * create a valid soft delete response control. 162 */ 163 public TransactionSettingsResponseControl(final String oid, 164 final boolean isCritical, 165 final ASN1OctetString value) 166 throws LDAPException 167 { 168 super(oid, isCritical, value); 169 170 if (value == null) 171 { 172 throw new LDAPException(ResultCode.DECODING_ERROR, 173 ERR_TXN_SETTINGS_RESPONSE_NO_VALUE.get()); 174 } 175 176 try 177 { 178 final ASN1Element[] elements = 179 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 180 numLockConflicts = ASN1Integer.decodeAsInteger(elements[0]).intValue(); 181 backendLockAcquired = 182 ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue(); 183 } 184 catch (final Exception e) 185 { 186 Debug.debugException(e); 187 throw new LDAPException(ResultCode.DECODING_ERROR, 188 ERR_TXN_SETTINGS_RESPONSE_ERROR_DECODING_VALUE.get( 189 StaticUtils.getExceptionMessage(e))); 190 } 191 } 192 193 194 195 /** 196 * Creates an encoded control value with the provided information. 197 * 198 * @param numLockConflicts The number of lock conflicts encountered 199 * during the course of processing the operation. 200 * @param backendLockAcquired Indicates whether the exclusive backend lock 201 * was acquired at any point during the course of 202 * processing the operation. 203 * 204 * @return An encoded control value with the provided information. 205 */ 206 private static ASN1OctetString encodeValue(final int numLockConflicts, 207 final boolean backendLockAcquired) 208 { 209 final ASN1Sequence valueSequence = new ASN1Sequence( 210 new ASN1Integer(TYPE_NUM_LOCK_CONFLICTS, numLockConflicts), 211 new ASN1Boolean(TYPE_BACKEND_LOCK_ACQUIRED, backendLockAcquired)); 212 return new ASN1OctetString(valueSequence.encode()); 213 } 214 215 216 217 /** 218 * {@inheritDoc} 219 */ 220 @Override() 221 public TransactionSettingsResponseControl decodeControl(final String oid, 222 final boolean isCritical, 223 final ASN1OctetString value) 224 throws LDAPException 225 { 226 return new TransactionSettingsResponseControl(oid, isCritical, value); 227 } 228 229 230 231 /** 232 * Retrieves the number of lock conflicts encountered during the course of 233 * processing the associated operation. 234 * 235 * @return The number of lock conflicts encountered during the course of 236 * processing the associated operation. 237 */ 238 public int getNumLockConflicts() 239 { 240 return numLockConflicts; 241 } 242 243 244 245 /** 246 * Indicates whether the exclusive backend lock was acquired at any point 247 * during the course of processing the associated operation. 248 * 249 * @return {@code true} if the backend lock was acquired, or {@code false} if 250 * not. 251 */ 252 public boolean backendLockAcquired() 253 { 254 return backendLockAcquired; 255 } 256 257 258 259 /** 260 * Extracts a transaction settings response control from the provided extended 261 * result. 262 * 263 * @param extendedResult The extended result from which to retrieve the 264 * transaction settings response control. 265 * 266 * @return The transaction settings response control contained in the 267 * provided extended result, or {@code null} if the result did not 268 * contain a transaction settings response control. 269 * 270 * @throws LDAPException If a problem is encountered while attempting to 271 * decode the transaction settings response control 272 * contained in the provided result. 273 */ 274 public static TransactionSettingsResponseControl 275 get(final ExtendedResult extendedResult) 276 throws LDAPException 277 { 278 final Control c = 279 extendedResult.getResponseControl(TRANSACTION_SETTINGS_RESPONSE_OID); 280 if (c == null) 281 { 282 return null; 283 } 284 285 if (c instanceof TransactionSettingsResponseControl) 286 { 287 return (TransactionSettingsResponseControl) c; 288 } 289 else 290 { 291 return new TransactionSettingsResponseControl(c.getOID(), c.isCritical(), 292 c.getValue()); 293 } 294 } 295 296 297 298 /** 299 * {@inheritDoc} 300 */ 301 @Override() 302 public String getControlName() 303 { 304 return INFO_CONTROL_NAME_TXN_SETTINGS_RESPONSE.get(); 305 } 306 307 308 309 /** 310 * {@inheritDoc} 311 */ 312 @Override() 313 public void toString(final StringBuilder buffer) 314 { 315 buffer.append("TransactionSettingsResponseControl(numLockConflicts="); 316 buffer.append(numLockConflicts); 317 buffer.append(", backendLockAcquired="); 318 buffer.append(backendLockAcquired); 319 buffer.append(')'); 320 } 321}