001/*
002 * Copyright 2009-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2009-2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.protocol;
037
038
039
040import com.unboundid.asn1.ASN1Buffer;
041import com.unboundid.asn1.ASN1BufferSequence;
042import com.unboundid.asn1.ASN1Element;
043import com.unboundid.asn1.ASN1OctetString;
044import com.unboundid.asn1.ASN1Sequence;
045import com.unboundid.asn1.ASN1StreamReader;
046import com.unboundid.asn1.ASN1StreamReaderSequence;
047import com.unboundid.ldap.sdk.Control;
048import com.unboundid.ldap.sdk.ExtendedRequest;
049import com.unboundid.ldap.sdk.LDAPException;
050import com.unboundid.ldap.sdk.ResultCode;
051import com.unboundid.util.Debug;
052import com.unboundid.util.InternalUseOnly;
053import com.unboundid.util.NotMutable;
054import com.unboundid.util.StaticUtils;
055import com.unboundid.util.ThreadSafety;
056import com.unboundid.util.ThreadSafetyLevel;
057import com.unboundid.util.Validator;
058
059import static com.unboundid.ldap.protocol.ProtocolMessages.*;
060
061
062
063/**
064 * This class provides an implementation of an LDAP extended request protocol
065 * op.
066 */
067@InternalUseOnly()
068@NotMutable()
069@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
070public final class ExtendedRequestProtocolOp
071       implements ProtocolOp
072{
073  /**
074   * The BER type for the OID element.
075   */
076  public static final byte TYPE_OID = (byte) 0x80;
077
078
079
080  /**
081   * The BER type for the value element.
082   */
083  public static final byte TYPE_VALUE = (byte) 0x81;
084
085
086
087  /**
088   * The serial version UID for this serializable class.
089   */
090  private static final long serialVersionUID = -5343424210200494377L;
091
092
093
094  // The value for this extended request.
095  private final ASN1OctetString value;
096
097  // The OID for this extended request.
098  private final String oid;
099
100
101
102  /**
103   * Creates a new extended request protocol op with the provided information.
104   *
105   * @param  oid    The OID for this extended request.
106   * @param  value  The value for this extended request, or {@code null} if
107   *                there should not be a value.
108   */
109  public ExtendedRequestProtocolOp(final String oid,
110                                   final ASN1OctetString value)
111  {
112    this.oid = oid;
113
114    if (value == null)
115    {
116      this.value = null;
117    }
118    else
119    {
120      this.value = new ASN1OctetString(TYPE_VALUE, value.getValue());
121    }
122  }
123
124
125
126  /**
127   * Creates a new extended request protocol op from the provided extended
128   * request object.
129   *
130   * @param  request  The extended request object to use to create this protocol
131   *                  op.
132   */
133  public ExtendedRequestProtocolOp(final ExtendedRequest request)
134  {
135    oid   = request.getOID();
136    value = request.getValue();
137  }
138
139
140
141  /**
142   * Creates a new extended request protocol op read from the provided ASN.1
143   * stream reader.
144   *
145   * @param  reader  The ASN.1 stream reader from which to read the extended
146   *                 request protocol op.
147   *
148   * @throws  LDAPException  If a problem occurs while reading or parsing the
149   *                         extended request.
150   */
151  ExtendedRequestProtocolOp(final ASN1StreamReader reader)
152       throws LDAPException
153  {
154    try
155    {
156      final ASN1StreamReaderSequence opSequence = reader.beginSequence();
157      oid = reader.readString();
158      Validator.ensureNotNull(oid);
159
160      if (opSequence.hasMoreElements())
161      {
162        value = new ASN1OctetString(TYPE_VALUE, reader.readBytes());
163      }
164      else
165      {
166        value = null;
167      }
168    }
169    catch (final Exception e)
170    {
171      Debug.debugException(e);
172
173      throw new LDAPException(ResultCode.DECODING_ERROR,
174           ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(
175                StaticUtils.getExceptionMessage(e)),
176           e);
177    }
178  }
179
180
181
182  /**
183   * Retrieves the OID for this extended request.
184   *
185   * @return  The OID for this extended request.
186   */
187  public String getOID()
188  {
189    return oid;
190  }
191
192
193
194  /**
195   * Retrieves the value for this extended request, if any.
196   *
197   * @return  The value for this extended request, or {@code null} if there is
198   *          no value.
199   */
200  public ASN1OctetString getValue()
201  {
202    return value;
203  }
204
205
206
207  /**
208   * {@inheritDoc}
209   */
210  @Override()
211  public byte getProtocolOpType()
212  {
213    return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST;
214  }
215
216
217
218  /**
219   * {@inheritDoc}
220   */
221  @Override()
222  public ASN1Element encodeProtocolOp()
223  {
224    if (value ==  null)
225    {
226      return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
227           new ASN1OctetString(TYPE_OID, oid));
228    }
229    else
230    {
231      return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
232           new ASN1OctetString(TYPE_OID, oid),
233           value);
234    }
235  }
236
237
238
239  /**
240   * Decodes the provided ASN.1 element as an extended request protocol op.
241   *
242   * @param  element  The ASN.1 element to be decoded.
243   *
244   * @return  The decoded extended request protocol op.
245   *
246   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
247   *                         an extended request protocol op.
248   */
249  public static ExtendedRequestProtocolOp decodeProtocolOp(
250                                               final ASN1Element element)
251         throws LDAPException
252  {
253    try
254    {
255      final ASN1Element[] elements =
256           ASN1Sequence.decodeAsSequence(element).elements();
257      final String oid =
258           ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
259
260      final ASN1OctetString value;
261      if (elements.length == 1)
262      {
263        value = null;
264      }
265      else
266      {
267        value = ASN1OctetString.decodeAsOctetString(elements[1]);
268      }
269
270      return new ExtendedRequestProtocolOp(oid, value);
271    }
272    catch (final Exception e)
273    {
274      Debug.debugException(e);
275      throw new LDAPException(ResultCode.DECODING_ERROR,
276           ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(
277                StaticUtils.getExceptionMessage(e)),
278           e);
279    }
280  }
281
282
283
284  /**
285   * {@inheritDoc}
286   */
287  @Override()
288  public void writeTo(final ASN1Buffer buffer)
289  {
290    final ASN1BufferSequence opSequence =
291         buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST);
292    buffer.addOctetString(TYPE_OID, oid);
293
294    if (value != null)
295    {
296      buffer.addOctetString(TYPE_VALUE, value.getValue());
297    }
298    opSequence.end();
299  }
300
301
302
303  /**
304   * Creates an extended request from this protocol op.
305   *
306   * @param  controls  The set of controls to include in the extended request.
307   *                   It may be empty or {@code null} if no controls should be
308   *                   included.
309   *
310   * @return  The extended request that was created.
311   */
312  public ExtendedRequest toExtendedRequest(final Control... controls)
313  {
314    return new ExtendedRequest(oid, value, controls);
315  }
316
317
318
319  /**
320   * Retrieves a string representation of this protocol op.
321   *
322   * @return  A string representation of this protocol op.
323   */
324  @Override()
325  public String toString()
326  {
327    final StringBuilder buffer = new StringBuilder();
328    toString(buffer);
329    return buffer.toString();
330  }
331
332
333
334  /**
335   * {@inheritDoc}
336   */
337  @Override()
338  public void toString(final StringBuilder buffer)
339  {
340    buffer.append("ExtendedRequestProtocolOp(oid='");
341    buffer.append(oid);
342    buffer.append("')");
343  }
344}