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