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