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    }