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 value = response.getValue();
125 }
126
127
128
129 /**
130 * Creates a new intermediate response protocol op read from the provided
131 * ASN.1 stream reader.
132 *
133 * @param reader The ASN.1 stream reader from which to read the intermediate
134 * response protocol op.
135 *
136 * @throws LDAPException If a problem occurs while reading or parsing the
137 * intermediate response.
138 */
139 IntermediateResponseProtocolOp(final ASN1StreamReader reader)
140 throws LDAPException
141 {
142 try
143 {
144 final ASN1StreamReaderSequence opSequence = reader.beginSequence();
145
146 String o = null;
147 ASN1OctetString v = null;
148 while (opSequence.hasMoreElements())
149 {
150 final byte type = (byte) reader.peek();
151 if (type == TYPE_OID)
152 {
153 o = reader.readString();
154 }
155 else if (type == TYPE_VALUE)
156 {
157 v = new ASN1OctetString(type, reader.readBytes());
158 }
159 else
160 {
161 throw new LDAPException(ResultCode.DECODING_ERROR,
162 ERR_INTERMEDIATE_RESPONSE_INVALID_ELEMENT.get(toHex(type)));
163 }
164 }
165
166 oid = o;
167 value = v;
168 }
169 catch (LDAPException le)
170 {
171 debugException(le);
172 throw le;
173 }
174 catch (Exception e)
175 {
176 debugException(e);
177
178 throw new LDAPException(ResultCode.DECODING_ERROR,
179 ERR_INTERMEDIATE_RESPONSE_CANNOT_DECODE.get(getExceptionMessage(e)),
180 e);
181 }
182 }
183
184
185
186 /**
187 * Retrieves the OID for this intermediate response, if any.
188 *
189 * @return The OID for this intermediate response, or {@code null} if there
190 * is no response OID.
191 */
192 public String getOID()
193 {
194 return oid;
195 }
196
197
198
199 /**
200 * Retrieves the value for this intermediate response, if any.
201 *
202 * @return The value for this intermediate response, or {@code null} if there
203 * is no response value.
204 */
205 public ASN1OctetString getValue()
206 {
207 return value;
208 }
209
210
211
212 /**
213 * {@inheritDoc}
214 */
215 public byte getProtocolOpType()
216 {
217 return LDAPMessage.PROTOCOL_OP_TYPE_INTERMEDIATE_RESPONSE;
218 }
219
220
221
222 /**
223 * {@inheritDoc}
224 */
225 public ASN1Element encodeProtocolOp()
226 {
227 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
228
229 if (oid != null)
230 {
231 elements.add(new ASN1OctetString(TYPE_OID, oid));
232 }
233
234 if (value != null)
235 {
236 elements.add(value);
237 }
238
239 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_INTERMEDIATE_RESPONSE,
240 elements);
241 }
242
243
244
245 /**
246 * Decodes the provided ASN.1 element as a intermediate response protocol op.
247 *
248 * @param element The ASN.1 element to be decoded.
249 *
250 * @return The decoded intermediate response protocol op.
251 *
252 * @throws LDAPException If the provided ASN.1 element cannot be decoded as
253 * a intermediate response protocol op.
254 */
255 public static IntermediateResponseProtocolOp decodeProtocolOp(
256 final ASN1Element element)
257 throws LDAPException
258 {
259 try
260 {
261 String oid = null;
262 ASN1OctetString value = null;
263 for (final ASN1Element e :
264 ASN1Sequence.decodeAsSequence(element).elements())
265 {
266 switch (e.getType())
267 {
268 case TYPE_OID:
269 oid = ASN1OctetString.decodeAsOctetString(e).stringValue();
270 break;
271 case TYPE_VALUE:
272 value = ASN1OctetString.decodeAsOctetString(e);
273 break;
274 default:
275 throw new LDAPException(ResultCode.DECODING_ERROR,
276 ERR_INTERMEDIATE_RESPONSE_INVALID_ELEMENT.get(
277 toHex(e.getType())));
278 }
279 }
280
281 return new IntermediateResponseProtocolOp(oid, value);
282 }
283 catch (final LDAPException le)
284 {
285 debugException(le);
286 throw le;
287 }
288 catch (final Exception e)
289 {
290 debugException(e);
291 throw new LDAPException(ResultCode.DECODING_ERROR,
292 ERR_COMPARE_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
293 e);
294 }
295 }
296
297
298
299 /**
300 * {@inheritDoc}
301 */
302 public void writeTo(final ASN1Buffer buffer)
303 {
304 final ASN1BufferSequence opSequence = buffer.beginSequence(
305 LDAPMessage.PROTOCOL_OP_TYPE_INTERMEDIATE_RESPONSE);
306
307 if (oid != null)
308 {
309 buffer.addOctetString(TYPE_OID, oid);
310 }
311
312 if (value != null)
313 {
314 buffer.addElement(value);
315 }
316
317 opSequence.end();
318 }
319
320
321
322 /**
323 * Creates a intermediate response from this protocol op.
324 *
325 * @param controls The set of controls to include in the intermediate
326 * response. It may be empty or {@code null} if no controls
327 * should be included.
328 *
329 * @return The intermediate response that was created.
330 */
331 public IntermediateResponse toIntermediateResponse(final Control... controls)
332 {
333 return new IntermediateResponse(-1, oid, value, controls);
334 }
335
336
337
338 /**
339 * Retrieves a string representation of this protocol op.
340 *
341 * @return A string representation of this protocol op.
342 */
343 @Override()
344 public String toString()
345 {
346 final StringBuilder buffer = new StringBuilder();
347 toString(buffer);
348 return buffer.toString();
349 }
350
351
352
353 /**
354 * {@inheritDoc}
355 */
356 public void toString(final StringBuilder buffer)
357 {
358 buffer.append("IntermediateResponseProtocolOp(");
359
360 if (oid != null)
361 {
362 buffer.append("oid='");
363 buffer.append(oid);
364 buffer.append('\'');
365 }
366
367 buffer.append(')');
368 }
369 }