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