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.NotMutable; 037import com.unboundid.util.InternalUseOnly; 038import com.unboundid.util.ThreadSafety; 039import com.unboundid.util.ThreadSafetyLevel; 040 041import static com.unboundid.ldap.protocol.ProtocolMessages.*; 042import static com.unboundid.util.Debug.*; 043import static com.unboundid.util.StaticUtils.*; 044import static com.unboundid.util.Validator.*; 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 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 debugException(e); 157 158 throw new LDAPException(ResultCode.DECODING_ERROR, 159 ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e); 160 } 161 } 162 163 164 165 /** 166 * Retrieves the OID for this extended request. 167 * 168 * @return The OID for this extended request. 169 */ 170 public String getOID() 171 { 172 return oid; 173 } 174 175 176 177 /** 178 * Retrieves the value for this extended request, if any. 179 * 180 * @return The value for this extended request, or {@code null} if there is 181 * no value. 182 */ 183 public ASN1OctetString getValue() 184 { 185 return value; 186 } 187 188 189 190 /** 191 * {@inheritDoc} 192 */ 193 @Override() 194 public byte getProtocolOpType() 195 { 196 return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST; 197 } 198 199 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override() 205 public ASN1Element encodeProtocolOp() 206 { 207 if (value == null) 208 { 209 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 210 new ASN1OctetString(TYPE_OID, oid)); 211 } 212 else 213 { 214 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 215 new ASN1OctetString(TYPE_OID, oid), 216 value); 217 } 218 } 219 220 221 222 /** 223 * Decodes the provided ASN.1 element as an extended request protocol op. 224 * 225 * @param element The ASN.1 element to be decoded. 226 * 227 * @return The decoded extended request protocol op. 228 * 229 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 230 * an extended request protocol op. 231 */ 232 public static ExtendedRequestProtocolOp decodeProtocolOp( 233 final ASN1Element element) 234 throws LDAPException 235 { 236 try 237 { 238 final ASN1Element[] elements = 239 ASN1Sequence.decodeAsSequence(element).elements(); 240 final String oid = 241 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 242 243 final ASN1OctetString value; 244 if (elements.length == 1) 245 { 246 value = null; 247 } 248 else 249 { 250 value = ASN1OctetString.decodeAsOctetString(elements[1]); 251 } 252 253 return new ExtendedRequestProtocolOp(oid, value); 254 } 255 catch (final Exception e) 256 { 257 debugException(e); 258 throw new LDAPException(ResultCode.DECODING_ERROR, 259 ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), 260 e); 261 } 262 } 263 264 265 266 /** 267 * {@inheritDoc} 268 */ 269 @Override() 270 public void writeTo(final ASN1Buffer buffer) 271 { 272 final ASN1BufferSequence opSequence = 273 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST); 274 buffer.addOctetString(TYPE_OID, oid); 275 276 if (value != null) 277 { 278 buffer.addOctetString(TYPE_VALUE, value.getValue()); 279 } 280 opSequence.end(); 281 } 282 283 284 285 /** 286 * Creates an extended request from this protocol op. 287 * 288 * @param controls The set of controls to include in the extended request. 289 * It may be empty or {@code null} if no controls should be 290 * included. 291 * 292 * @return The extended request that was created. 293 */ 294 public ExtendedRequest toExtendedRequest(final Control... controls) 295 { 296 return new ExtendedRequest(oid, value, controls); 297 } 298 299 300 301 /** 302 * Retrieves a string representation of this protocol op. 303 * 304 * @return A string representation of this protocol op. 305 */ 306 @Override() 307 public String toString() 308 { 309 final StringBuilder buffer = new StringBuilder(); 310 toString(buffer); 311 return buffer.toString(); 312 } 313 314 315 316 /** 317 * {@inheritDoc} 318 */ 319 @Override() 320 public void toString(final StringBuilder buffer) 321 { 322 buffer.append("ExtendedRequestProtocolOp(oid='"); 323 buffer.append(oid); 324 buffer.append("')"); 325 } 326}