001/*
002 * Copyright 2009-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2009-2019 Ping Identity Corporation
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.Debug;
037import com.unboundid.util.InternalUseOnly;
038import com.unboundid.util.NotMutable;
039import com.unboundid.util.StaticUtils;
040import com.unboundid.util.ThreadSafety;
041import com.unboundid.util.ThreadSafetyLevel;
042import com.unboundid.util.Validator;
043
044import static com.unboundid.ldap.protocol.ProtocolMessages.*;
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      Validator.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 (final Exception e)
155    {
156      Debug.debugException(e);
157
158      throw new LDAPException(ResultCode.DECODING_ERROR,
159           ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(
160                StaticUtils.getExceptionMessage(e)),
161           e);
162    }
163  }
164
165
166
167  /**
168   * Retrieves the OID for this extended request.
169   *
170   * @return  The OID for this extended request.
171   */
172  public String getOID()
173  {
174    return oid;
175  }
176
177
178
179  /**
180   * Retrieves the value for this extended request, if any.
181   *
182   * @return  The value for this extended request, or {@code null} if there is
183   *          no value.
184   */
185  public ASN1OctetString getValue()
186  {
187    return value;
188  }
189
190
191
192  /**
193   * {@inheritDoc}
194   */
195  @Override()
196  public byte getProtocolOpType()
197  {
198    return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST;
199  }
200
201
202
203  /**
204   * {@inheritDoc}
205   */
206  @Override()
207  public ASN1Element encodeProtocolOp()
208  {
209    if (value ==  null)
210    {
211      return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
212           new ASN1OctetString(TYPE_OID, oid));
213    }
214    else
215    {
216      return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
217           new ASN1OctetString(TYPE_OID, oid),
218           value);
219    }
220  }
221
222
223
224  /**
225   * Decodes the provided ASN.1 element as an extended request protocol op.
226   *
227   * @param  element  The ASN.1 element to be decoded.
228   *
229   * @return  The decoded extended request protocol op.
230   *
231   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
232   *                         an extended request protocol op.
233   */
234  public static ExtendedRequestProtocolOp decodeProtocolOp(
235                                               final ASN1Element element)
236         throws LDAPException
237  {
238    try
239    {
240      final ASN1Element[] elements =
241           ASN1Sequence.decodeAsSequence(element).elements();
242      final String oid =
243           ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
244
245      final ASN1OctetString value;
246      if (elements.length == 1)
247      {
248        value = null;
249      }
250      else
251      {
252        value = ASN1OctetString.decodeAsOctetString(elements[1]);
253      }
254
255      return new ExtendedRequestProtocolOp(oid, value);
256    }
257    catch (final Exception e)
258    {
259      Debug.debugException(e);
260      throw new LDAPException(ResultCode.DECODING_ERROR,
261           ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(
262                StaticUtils.getExceptionMessage(e)),
263           e);
264    }
265  }
266
267
268
269  /**
270   * {@inheritDoc}
271   */
272  @Override()
273  public void writeTo(final ASN1Buffer buffer)
274  {
275    final ASN1BufferSequence opSequence =
276         buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST);
277    buffer.addOctetString(TYPE_OID, oid);
278
279    if (value != null)
280    {
281      buffer.addOctetString(TYPE_VALUE, value.getValue());
282    }
283    opSequence.end();
284  }
285
286
287
288  /**
289   * Creates an extended request from this protocol op.
290   *
291   * @param  controls  The set of controls to include in the extended request.
292   *                   It may be empty or {@code null} if no controls should be
293   *                   included.
294   *
295   * @return  The extended request that was created.
296   */
297  public ExtendedRequest toExtendedRequest(final Control... controls)
298  {
299    return new ExtendedRequest(oid, value, controls);
300  }
301
302
303
304  /**
305   * Retrieves a string representation of this protocol op.
306   *
307   * @return  A string representation of this protocol op.
308   */
309  @Override()
310  public String toString()
311  {
312    final StringBuilder buffer = new StringBuilder();
313    toString(buffer);
314    return buffer.toString();
315  }
316
317
318
319  /**
320   * {@inheritDoc}
321   */
322  @Override()
323  public void toString(final StringBuilder buffer)
324  {
325    buffer.append("ExtendedRequestProtocolOp(oid='");
326    buffer.append(oid);
327    buffer.append("')");
328  }
329}