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