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 */
021package com.unboundid.ldap.protocol;
022
023
024
025import java.util.ArrayList;
026
027import com.unboundid.asn1.ASN1Buffer;
028import com.unboundid.asn1.ASN1BufferSequence;
029import com.unboundid.asn1.ASN1Element;
030import com.unboundid.asn1.ASN1OctetString;
031import com.unboundid.asn1.ASN1Sequence;
032import com.unboundid.asn1.ASN1StreamReader;
033import com.unboundid.asn1.ASN1StreamReaderSequence;
034import com.unboundid.ldap.sdk.Control;
035import com.unboundid.ldap.sdk.IntermediateResponse;
036import com.unboundid.ldap.sdk.LDAPException;
037import com.unboundid.ldap.sdk.ResultCode;
038import com.unboundid.util.NotMutable;
039import com.unboundid.util.InternalUseOnly;
040import com.unboundid.util.ThreadSafety;
041import com.unboundid.util.ThreadSafetyLevel;
042
043import static com.unboundid.ldap.protocol.ProtocolMessages.*;
044import static com.unboundid.util.Debug.*;
045import 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)
056public 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}