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