001/* 002 * Copyright 2009-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2009-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.protocol; 022 023 024 025import com.unboundid.asn1.ASN1Buffer; 026import com.unboundid.asn1.ASN1BufferSequence; 027import com.unboundid.asn1.ASN1Element; 028import com.unboundid.asn1.ASN1OctetString; 029import com.unboundid.asn1.ASN1Sequence; 030import com.unboundid.asn1.ASN1StreamReader; 031import com.unboundid.asn1.ASN1StreamReaderSequence; 032import com.unboundid.ldap.sdk.Control; 033import com.unboundid.ldap.sdk.ExtendedRequest; 034import com.unboundid.ldap.sdk.LDAPException; 035import com.unboundid.ldap.sdk.ResultCode; 036import com.unboundid.util.Debug; 037import com.unboundid.util.InternalUseOnly; 038import com.unboundid.util.NotMutable; 039import com.unboundid.util.StaticUtils; 040import com.unboundid.util.ThreadSafety; 041import com.unboundid.util.ThreadSafetyLevel; 042import com.unboundid.util.Validator; 043 044import static com.unboundid.ldap.protocol.ProtocolMessages.*; 045 046 047 048/** 049 * This class provides an implementation of an LDAP extended request protocol 050 * op. 051 */ 052@InternalUseOnly() 053@NotMutable() 054@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 055public final class ExtendedRequestProtocolOp 056 implements ProtocolOp 057{ 058 /** 059 * The BER type for the OID element. 060 */ 061 public static final byte TYPE_OID = (byte) 0x80; 062 063 064 065 /** 066 * The BER type for the value element. 067 */ 068 public static final byte TYPE_VALUE = (byte) 0x81; 069 070 071 072 /** 073 * The serial version UID for this serializable class. 074 */ 075 private static final long serialVersionUID = -5343424210200494377L; 076 077 078 079 // The value for this extended request. 080 private final ASN1OctetString value; 081 082 // The OID for this extended request. 083 private final String oid; 084 085 086 087 /** 088 * Creates a new extended request protocol op with the provided information. 089 * 090 * @param oid The OID for this extended request. 091 * @param value The value for this extended request, or {@code null} if 092 * there should not be a value. 093 */ 094 public ExtendedRequestProtocolOp(final String oid, 095 final ASN1OctetString value) 096 { 097 this.oid = oid; 098 099 if (value == null) 100 { 101 this.value = null; 102 } 103 else 104 { 105 this.value = new ASN1OctetString(TYPE_VALUE, value.getValue()); 106 } 107 } 108 109 110 111 /** 112 * Creates a new extended request protocol op from the provided extended 113 * request object. 114 * 115 * @param request The extended request object to use to create this protocol 116 * op. 117 */ 118 public ExtendedRequestProtocolOp(final ExtendedRequest request) 119 { 120 oid = request.getOID(); 121 value = request.getValue(); 122 } 123 124 125 126 /** 127 * Creates a new extended request protocol op read from the provided ASN.1 128 * stream reader. 129 * 130 * @param reader The ASN.1 stream reader from which to read the extended 131 * request protocol op. 132 * 133 * @throws LDAPException If a problem occurs while reading or parsing the 134 * extended request. 135 */ 136 ExtendedRequestProtocolOp(final ASN1StreamReader reader) 137 throws LDAPException 138 { 139 try 140 { 141 final ASN1StreamReaderSequence opSequence = reader.beginSequence(); 142 oid = reader.readString(); 143 Validator.ensureNotNull(oid); 144 145 if (opSequence.hasMoreElements()) 146 { 147 value = new ASN1OctetString(TYPE_VALUE, reader.readBytes()); 148 } 149 else 150 { 151 value = null; 152 } 153 } 154 catch (final Exception e) 155 { 156 Debug.debugException(e); 157 158 throw new LDAPException(ResultCode.DECODING_ERROR, 159 ERR_EXTENDED_REQUEST_CANNOT_DECODE.get( 160 StaticUtils.getExceptionMessage(e)), 161 e); 162 } 163 } 164 165 166 167 /** 168 * Retrieves the OID for this extended request. 169 * 170 * @return The OID for this extended request. 171 */ 172 public String getOID() 173 { 174 return oid; 175 } 176 177 178 179 /** 180 * Retrieves the value for this extended request, if any. 181 * 182 * @return The value for this extended request, or {@code null} if there is 183 * no value. 184 */ 185 public ASN1OctetString getValue() 186 { 187 return value; 188 } 189 190 191 192 /** 193 * {@inheritDoc} 194 */ 195 @Override() 196 public byte getProtocolOpType() 197 { 198 return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST; 199 } 200 201 202 203 /** 204 * {@inheritDoc} 205 */ 206 @Override() 207 public ASN1Element encodeProtocolOp() 208 { 209 if (value == null) 210 { 211 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 212 new ASN1OctetString(TYPE_OID, oid)); 213 } 214 else 215 { 216 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 217 new ASN1OctetString(TYPE_OID, oid), 218 value); 219 } 220 } 221 222 223 224 /** 225 * Decodes the provided ASN.1 element as an extended request protocol op. 226 * 227 * @param element The ASN.1 element to be decoded. 228 * 229 * @return The decoded extended request protocol op. 230 * 231 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 232 * an extended request protocol op. 233 */ 234 public static ExtendedRequestProtocolOp decodeProtocolOp( 235 final ASN1Element element) 236 throws LDAPException 237 { 238 try 239 { 240 final ASN1Element[] elements = 241 ASN1Sequence.decodeAsSequence(element).elements(); 242 final String oid = 243 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 244 245 final ASN1OctetString value; 246 if (elements.length == 1) 247 { 248 value = null; 249 } 250 else 251 { 252 value = ASN1OctetString.decodeAsOctetString(elements[1]); 253 } 254 255 return new ExtendedRequestProtocolOp(oid, value); 256 } 257 catch (final Exception e) 258 { 259 Debug.debugException(e); 260 throw new LDAPException(ResultCode.DECODING_ERROR, 261 ERR_EXTENDED_REQUEST_CANNOT_DECODE.get( 262 StaticUtils.getExceptionMessage(e)), 263 e); 264 } 265 } 266 267 268 269 /** 270 * {@inheritDoc} 271 */ 272 @Override() 273 public void writeTo(final ASN1Buffer buffer) 274 { 275 final ASN1BufferSequence opSequence = 276 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST); 277 buffer.addOctetString(TYPE_OID, oid); 278 279 if (value != null) 280 { 281 buffer.addOctetString(TYPE_VALUE, value.getValue()); 282 } 283 opSequence.end(); 284 } 285 286 287 288 /** 289 * Creates an extended request from this protocol op. 290 * 291 * @param controls The set of controls to include in the extended request. 292 * It may be empty or {@code null} if no controls should be 293 * included. 294 * 295 * @return The extended request that was created. 296 */ 297 public ExtendedRequest toExtendedRequest(final Control... controls) 298 { 299 return new ExtendedRequest(oid, value, controls); 300 } 301 302 303 304 /** 305 * Retrieves a string representation of this protocol op. 306 * 307 * @return A string representation of this protocol op. 308 */ 309 @Override() 310 public String toString() 311 { 312 final StringBuilder buffer = new StringBuilder(); 313 toString(buffer); 314 return buffer.toString(); 315 } 316 317 318 319 /** 320 * {@inheritDoc} 321 */ 322 @Override() 323 public void toString(final StringBuilder buffer) 324 { 325 buffer.append("ExtendedRequestProtocolOp(oid='"); 326 buffer.append(oid); 327 buffer.append("')"); 328 } 329}