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 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.InternalUseOnly;
037    
038    import static com.unboundid.ldap.protocol.ProtocolMessages.*;
039    import static com.unboundid.util.Debug.*;
040    import static com.unboundid.util.StaticUtils.*;
041    import static com.unboundid.util.Validator.*;
042    
043    
044    
045    /**
046     * This class provides an implementation of an LDAP extended request protocol
047     * op.
048     */
049    @InternalUseOnly()
050    public final class ExtendedRequestProtocolOp
051           implements ProtocolOp
052    {
053      /**
054       * The BER type for the OID element.
055       */
056      public static final byte TYPE_OID = (byte) 0x80;
057    
058    
059    
060      /**
061       * The BER type for the value element.
062       */
063      public static final byte TYPE_VALUE = (byte) 0x81;
064    
065    
066    
067      /**
068       * The serial version UID for this serializable class.
069       */
070      private static final long serialVersionUID = -5343424210200494377L;
071    
072    
073    
074      // The value for this extended request.
075      private final ASN1OctetString value;
076    
077      // The OID for this extended request.
078      private final String oid;
079    
080    
081    
082      /**
083       * Creates a new extended request protocol op with the provided information.
084       *
085       * @param  oid    The OID for this extended request.
086       * @param  value  The value for this extended request, or {@code null} if
087       *                there should not be a value.
088       */
089      public ExtendedRequestProtocolOp(final String oid,
090                                       final ASN1OctetString value)
091      {
092        this.oid = oid;
093    
094        if (value == null)
095        {
096          this.value = null;
097        }
098        else
099        {
100          this.value = new ASN1OctetString(TYPE_VALUE, value.getValue());
101        }
102      }
103    
104    
105    
106      /**
107       * Creates a new extended request protocol op from the provided extended
108       * request object.
109       *
110       * @param  request  The extended request object to use to create this protocol
111       *                  op.
112       */
113      public ExtendedRequestProtocolOp(final ExtendedRequest request)
114      {
115        oid   = request.getOID();
116        value = request.getValue();
117      }
118    
119    
120    
121      /**
122       * Creates a new extended request protocol op read from the provided ASN.1
123       * stream reader.
124       *
125       * @param  reader  The ASN.1 stream reader from which to read the extended
126       *                 request protocol op.
127       *
128       * @throws  LDAPException  If a problem occurs while reading or parsing the
129       *                         extended request.
130       */
131      ExtendedRequestProtocolOp(final ASN1StreamReader reader)
132           throws LDAPException
133      {
134        try
135        {
136          final ASN1StreamReaderSequence opSequence = reader.beginSequence();
137          oid = reader.readString();
138          ensureNotNull(oid);
139    
140          if (opSequence.hasMoreElements())
141          {
142            value = new ASN1OctetString(TYPE_VALUE, reader.readBytes());
143          }
144          else
145          {
146            value = null;
147          }
148        }
149        catch (Exception e)
150        {
151          debugException(e);
152    
153          throw new LDAPException(ResultCode.DECODING_ERROR,
154               ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e);
155        }
156      }
157    
158    
159    
160      /**
161       * Retrieves the OID for this extended request.
162       *
163       * @return  The OID for this extended request.
164       */
165      public String getOID()
166      {
167        return oid;
168      }
169    
170    
171    
172      /**
173       * Retrieves the value for this extended request, if any.
174       *
175       * @return  The value for this extended request, or {@code null} if there is
176       *          no value.
177       */
178      public ASN1OctetString getValue()
179      {
180        return value;
181      }
182    
183    
184    
185      /**
186       * {@inheritDoc}
187       */
188      public byte getProtocolOpType()
189      {
190        return LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST;
191      }
192    
193    
194    
195      /**
196       * {@inheritDoc}
197       */
198      public ASN1Element encodeProtocolOp()
199      {
200        if (value ==  null)
201        {
202          return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
203               new ASN1OctetString(TYPE_OID, oid));
204        }
205        else
206        {
207          return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST,
208               new ASN1OctetString(TYPE_OID, oid),
209               value);
210        }
211      }
212    
213    
214    
215      /**
216       * Decodes the provided ASN.1 element as an extended request protocol op.
217       *
218       * @param  element  The ASN.1 element to be decoded.
219       *
220       * @return  The decoded extended request protocol op.
221       *
222       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
223       *                         an extended request protocol op.
224       */
225      public static ExtendedRequestProtocolOp decodeProtocolOp(
226                                                   final ASN1Element element)
227             throws LDAPException
228      {
229        try
230        {
231          final ASN1Element[] elements =
232               ASN1Sequence.decodeAsSequence(element).elements();
233          final String oid =
234               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
235    
236          final ASN1OctetString value;
237          if (elements.length == 1)
238          {
239            value = null;
240          }
241          else
242          {
243            value = ASN1OctetString.decodeAsOctetString(elements[1]);
244          }
245    
246          return new ExtendedRequestProtocolOp(oid, value);
247        }
248        catch (final Exception e)
249        {
250          debugException(e);
251          throw new LDAPException(ResultCode.DECODING_ERROR,
252               ERR_EXTENDED_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
253               e);
254        }
255      }
256    
257    
258    
259      /**
260       * {@inheritDoc}
261       */
262      public void writeTo(final ASN1Buffer buffer)
263      {
264        final ASN1BufferSequence opSequence =
265             buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST);
266        buffer.addOctetString(TYPE_OID, oid);
267    
268        if (value != null)
269        {
270          buffer.addOctetString(TYPE_VALUE, value.getValue());
271        }
272        opSequence.end();
273      }
274    
275    
276    
277      /**
278       * Creates an extended request from this protocol op.
279       *
280       * @param  controls  The set of controls to include in the extended request.
281       *                   It may be empty or {@code null} if no controls should be
282       *                   included.
283       *
284       * @return  The extended request that was created.
285       */
286      public ExtendedRequest toExtendedRequest(final Control... controls)
287      {
288        return new ExtendedRequest(oid, value, controls);
289      }
290    
291    
292    
293      /**
294       * Retrieves a string representation of this protocol op.
295       *
296       * @return  A string representation of this protocol op.
297       */
298      @Override()
299      public String toString()
300      {
301        final StringBuilder buffer = new StringBuilder();
302        toString(buffer);
303        return buffer.toString();
304      }
305    
306    
307    
308      /**
309       * {@inheritDoc}
310       */
311      public void toString(final StringBuilder buffer)
312      {
313        buffer.append("ExtendedRequestProtocolOp(oid='");
314        buffer.append(oid);
315        buffer.append("')");
316      }
317    }