001/* 002 * Copyright 2009-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2009-2017 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 */ 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 (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 public byte getProtocolOpType() 194 { 195 return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST; 196 } 197 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 public ASN1Element encodeProtocolOp() 204 { 205 if (value == null) 206 { 207 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 208 new ASN1OctetString(TYPE_OID, oid)); 209 } 210 else 211 { 212 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST, 213 new ASN1OctetString(TYPE_OID, oid), 214 value); 215 } 216 } 217 218 219 220 /** 221 * Decodes the provided ASN.1 element as an extended request protocol op. 222 * 223 * @param element The ASN.1 element to be decoded. 224 * 225 * @return The decoded extended request protocol op. 226 * 227 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 228 * an extended request protocol op. 229 */ 230 public static ExtendedRequestProtocolOp decodeProtocolOp( 231 final ASN1Element element) 232 throws LDAPException 233 { 234 try 235 { 236 final ASN1Element[] elements = 237 ASN1Sequence.decodeAsSequence(element).elements(); 238 final String oid = 239 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 240 241 final ASN1OctetString value; 242 if (elements.length == 1) 243 { 244 value = null; 245 } 246 else 247 { 248 value = ASN1OctetString.decodeAsOctetString(elements[1]); 249 } 250 251 return new ExtendedRequestProtocolOp(oid, value); 252 } 253 catch (final Exception e) 254 { 255 debugException(e); 256 throw new LDAPException(ResultCode.DECODING_ERROR, 257 ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), 258 e); 259 } 260 } 261 262 263 264 /** 265 * {@inheritDoc} 266 */ 267 public void writeTo(final ASN1Buffer buffer) 268 { 269 final ASN1BufferSequence opSequence = 270 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST); 271 buffer.addOctetString(TYPE_OID, oid); 272 273 if (value != null) 274 { 275 buffer.addOctetString(TYPE_VALUE, value.getValue()); 276 } 277 opSequence.end(); 278 } 279 280 281 282 /** 283 * Creates an extended request from this protocol op. 284 * 285 * @param controls The set of controls to include in the extended request. 286 * It may be empty or {@code null} if no controls should be 287 * included. 288 * 289 * @return The extended request that was created. 290 */ 291 public ExtendedRequest toExtendedRequest(final Control... controls) 292 { 293 return new ExtendedRequest(oid, value, controls); 294 } 295 296 297 298 /** 299 * Retrieves a string representation of this protocol op. 300 * 301 * @return A string representation of this protocol op. 302 */ 303 @Override() 304 public String toString() 305 { 306 final StringBuilder buffer = new StringBuilder(); 307 toString(buffer); 308 return buffer.toString(); 309 } 310 311 312 313 /** 314 * {@inheritDoc} 315 */ 316 public void toString(final StringBuilder buffer) 317 { 318 buffer.append("ExtendedRequestProtocolOp(oid='"); 319 buffer.append(oid); 320 buffer.append("')"); 321 } 322}