001    /*
002     * Copyright 2007-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.extensions;
022    
023    
024    
025    import com.unboundid.asn1.ASN1Boolean;
026    import com.unboundid.asn1.ASN1Element;
027    import com.unboundid.asn1.ASN1OctetString;
028    import com.unboundid.asn1.ASN1Sequence;
029    import com.unboundid.ldap.sdk.Control;
030    import com.unboundid.ldap.sdk.ExtendedRequest;
031    import com.unboundid.ldap.sdk.ExtendedResult;
032    import com.unboundid.ldap.sdk.LDAPConnection;
033    import com.unboundid.ldap.sdk.LDAPException;
034    import com.unboundid.ldap.sdk.ResultCode;
035    import com.unboundid.util.NotMutable;
036    import com.unboundid.util.ThreadSafety;
037    import com.unboundid.util.ThreadSafetyLevel;
038    
039    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
040    import static com.unboundid.util.Debug.*;
041    import static com.unboundid.util.Validator.*;
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 an implementation of the end batched transaction extended
053     * request.  It may be used to either commit or abort a transaction that was
054     * created using the start batched transaction request.  See the documentation
055     * for the {@link StartBatchedTransactionExtendedRequest} for an example of
056     * processing a batched transaction.
057     */
058    @NotMutable()
059    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
060    public final class EndBatchedTransactionExtendedRequest
061           extends ExtendedRequest
062    {
063      /**
064       * The OID (1.3.6.1.4.1.30221.2.6.2) for the end batched transaction extended
065       * request.
066       */
067      public static final String END_BATCHED_TRANSACTION_REQUEST_OID =
068           "1.3.6.1.4.1.30221.2.6.2";
069    
070    
071    
072      /**
073       * The serial version UID for this serializable class.
074       */
075      private static final long serialVersionUID = -8569129721687583552L;
076    
077    
078    
079      // The transaction ID for the associated transaction.
080      private final ASN1OctetString transactionID;
081    
082      // Indicates whether to commit or abort the associated transaction.
083      private final boolean commit;
084    
085    
086    
087      /**
088       * Creates a new end batched transaction extended request with the provided
089       * information.
090       *
091       * @param  transactionID  The transaction ID for the transaction to commit or
092       *                        abort.  It must not be {@code null}.
093       * @param  commit         {@code true} if the transaction should be committed,
094       *                        or {@code false} if the transaction should be
095       *                        aborted.
096       */
097      public EndBatchedTransactionExtendedRequest(
098                  final ASN1OctetString transactionID, final boolean commit)
099      {
100        this(transactionID, commit, null);
101      }
102    
103    
104    
105      /**
106       * Creates a new end batched transaction extended request with the provided
107       * information.
108       *
109       * @param  transactionID  The transaction ID for the transaction to commit or
110       *                        abort.  It must not be {@code null}.
111       * @param  commit         {@code true} if the transaction should be committed,
112       *                        or {@code false} if the transaction should be
113       *                        aborted.
114       * @param  controls       The set of controls to include in the request.
115       */
116      public EndBatchedTransactionExtendedRequest(
117                  final ASN1OctetString transactionID, final boolean commit,
118                  final Control[] controls)
119      {
120        super(END_BATCHED_TRANSACTION_REQUEST_OID,
121              encodeValue(transactionID, commit),
122              controls);
123    
124        this.transactionID = transactionID;
125        this.commit        = commit;
126      }
127    
128    
129    
130      /**
131       * Creates a new end batched transaction extended request from the provided
132       * generic extended request.
133       *
134       * @param  extendedRequest  The generic extended request to use to create this
135       *                          end batched transaction extended request.
136       *
137       * @throws  LDAPException  If a problem occurs while decoding the request.
138       */
139      public EndBatchedTransactionExtendedRequest(
140                  final ExtendedRequest extendedRequest)
141             throws LDAPException
142      {
143        super(extendedRequest);
144    
145        final ASN1OctetString value = extendedRequest.getValue();
146        if (value == null)
147        {
148          throw new LDAPException(ResultCode.DECODING_ERROR,
149                                  ERR_END_TXN_REQUEST_NO_VALUE.get());
150        }
151    
152        try
153        {
154          final ASN1Element valueElement = ASN1Element.decode(value.getValue());
155          final ASN1Element[] elements =
156               ASN1Sequence.decodeAsSequence(valueElement).elements();
157          if (elements.length == 1)
158          {
159            commit        = true;
160            transactionID = ASN1OctetString.decodeAsOctetString(elements[0]);
161          }
162          else
163          {
164            commit        = ASN1Boolean.decodeAsBoolean(elements[0]).booleanValue();
165            transactionID = ASN1OctetString.decodeAsOctetString(elements[1]);
166          }
167        }
168        catch (Exception e)
169        {
170          debugException(e);
171          throw new LDAPException(ResultCode.DECODING_ERROR,
172                                  ERR_END_TXN_REQUEST_CANNOT_DECODE.get(e), e);
173        }
174      }
175    
176    
177    
178      /**
179       * Generates the value to include in this extended request.
180       *
181       * @param  transactionID  The transaction ID for the transaction to commit or
182       *                        abort.  It must not be {@code null}.
183       * @param  commit         {@code true} if the transaction should be committed,
184       *                        or {@code false} if the transaction should be
185       *                        aborted.
186       *
187       * @return  The ASN.1 octet string containing the encoded request value.
188       */
189      private static ASN1OctetString
190           encodeValue(final ASN1OctetString transactionID,
191                       final boolean commit)
192      {
193        ensureNotNull(transactionID);
194    
195        final ASN1Element[] valueElements;
196        if (commit)
197        {
198          valueElements = new ASN1Element[]
199          {
200            transactionID
201          };
202        }
203        else
204        {
205          valueElements = new ASN1Element[]
206          {
207            new ASN1Boolean(commit),
208            transactionID
209          };
210        }
211    
212        return new ASN1OctetString(new ASN1Sequence(valueElements).encode());
213      }
214    
215    
216    
217      /**
218       * Retrieves the transaction ID for the transaction to commit or abort.
219       *
220       * @return  The transaction ID for the transaction to commit or abort.
221       */
222      public ASN1OctetString getTransactionID()
223      {
224        return transactionID;
225      }
226    
227    
228    
229      /**
230       * Indicates whether the transaction should be committed or aborted.
231       *
232       * @return  {@code true} if the transaction should be committed, or
233       *          {@code false} if it should be aborted.
234       */
235      public boolean commit()
236      {
237        return commit;
238      }
239    
240    
241    
242      /**
243       * {@inheritDoc}
244       */
245      @Override()
246      public EndBatchedTransactionExtendedResult process(
247                  final LDAPConnection connection, final int depth)
248             throws LDAPException
249      {
250        final ExtendedResult extendedResponse = super.process(connection, depth);
251        return new EndBatchedTransactionExtendedResult(extendedResponse);
252      }
253    
254    
255    
256      /**
257       * {@inheritDoc}
258       */
259      @Override()
260      public EndBatchedTransactionExtendedRequest duplicate()
261      {
262        return duplicate(getControls());
263      }
264    
265    
266    
267      /**
268       * {@inheritDoc}
269       */
270      @Override()
271      public EndBatchedTransactionExtendedRequest duplicate(
272                  final Control[] controls)
273      {
274        final EndBatchedTransactionExtendedRequest r =
275             new EndBatchedTransactionExtendedRequest(transactionID, commit,
276                  controls);
277        r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
278        return r;
279      }
280    
281    
282    
283      /**
284       * {@inheritDoc}
285       */
286      @Override()
287      public String getExtendedRequestName()
288      {
289        return INFO_EXTENDED_REQUEST_NAME_END_BATCHED_TXN.get();
290      }
291    
292    
293    
294      /**
295       * {@inheritDoc}
296       */
297      @Override()
298      public void toString(final StringBuilder buffer)
299      {
300        buffer.append("EndBatchedTransactionExtendedRequest(transactionID='");
301        buffer.append(transactionID.stringValue());
302        buffer.append("', commit=");
303        buffer.append(commit);
304    
305        final Control[] controls = getControls();
306        if (controls.length > 0)
307        {
308          buffer.append("controls={");
309          for (int i=0; i < controls.length; i++)
310          {
311            if (i > 0)
312            {
313              buffer.append(", ");
314            }
315    
316            buffer.append(controls[i]);
317          }
318          buffer.append('}');
319        }
320    
321        buffer.append(')');
322      }
323    }