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