001/*
002 * Copyright 2007-2023 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2007-2023 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) 2007-2023 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.sdk;
037
038
039
040import java.io.Serializable;
041import java.lang.reflect.Constructor;
042import java.util.ArrayList;
043import java.util.LinkedHashMap;
044import java.util.Map;
045import java.util.concurrent.ConcurrentHashMap;
046
047import com.unboundid.asn1.ASN1Boolean;
048import com.unboundid.asn1.ASN1Buffer;
049import com.unboundid.asn1.ASN1BufferSequence;
050import com.unboundid.asn1.ASN1Constants;
051import com.unboundid.asn1.ASN1Element;
052import com.unboundid.asn1.ASN1Exception;
053import com.unboundid.asn1.ASN1OctetString;
054import com.unboundid.asn1.ASN1Sequence;
055import com.unboundid.asn1.ASN1StreamReader;
056import com.unboundid.asn1.ASN1StreamReaderSequence;
057import com.unboundid.ldap.sdk.controls.AssertionRequestControl;
058import com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl;
059import com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl;
060import com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl;
061import com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl;
062import com.unboundid.ldap.sdk.controls.MatchedValuesRequestControl;
063import com.unboundid.ldap.sdk.controls.PasswordExpiredControl;
064import com.unboundid.ldap.sdk.controls.PasswordExpiringControl;
065import com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl;
066import com.unboundid.ldap.sdk.controls.PostReadRequestControl;
067import com.unboundid.ldap.sdk.controls.PostReadResponseControl;
068import com.unboundid.ldap.sdk.controls.PreReadRequestControl;
069import com.unboundid.ldap.sdk.controls.PreReadResponseControl;
070import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl;
071import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl;
072import com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl;
073import com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl;
074import com.unboundid.ldap.sdk.controls.SimplePagedResultsControl;
075import com.unboundid.ldap.sdk.controls.SubtreeDeleteRequestControl;
076import com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl;
077import com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl;
078import com.unboundid.ldap.sdk.unboundidds.controls.AccessLogFieldRequestControl;
079import com.unboundid.ldap.sdk.unboundidds.controls.AccountUsableRequestControl;
080import com.unboundid.ldap.sdk.unboundidds.controls.AccountUsableResponseControl;
081import com.unboundid.ldap.sdk.unboundidds.controls.
082            AdministrativeOperationRequestControl;
083import com.unboundid.ldap.sdk.unboundidds.controls.
084            AssuredReplicationRequestControl;
085import com.unboundid.ldap.sdk.unboundidds.controls.
086            AssuredReplicationResponseControl;
087import com.unboundid.ldap.sdk.unboundidds.controls.ExcludeBranchRequestControl;
088import com.unboundid.ldap.sdk.unboundidds.controls.
089            ExtendedSchemaInfoRequestControl;
090import com.unboundid.ldap.sdk.unboundidds.controls.
091            GenerateAccessTokenRequestControl;
092import com.unboundid.ldap.sdk.unboundidds.controls.
093            GenerateAccessTokenResponseControl;
094import com.unboundid.ldap.sdk.unboundidds.controls.
095            GeneratePasswordRequestControl;
096import com.unboundid.ldap.sdk.unboundidds.controls.
097            GeneratePasswordResponseControl;
098import com.unboundid.ldap.sdk.unboundidds.controls.
099            GetAuthorizationEntryRequestControl;
100import com.unboundid.ldap.sdk.unboundidds.controls.
101            GetAuthorizationEntryResponseControl;
102import com.unboundid.ldap.sdk.unboundidds.controls.
103            GetBackendSetIDRequestControl;
104import com.unboundid.ldap.sdk.unboundidds.controls.
105            GetBackendSetIDResponseControl;
106import com.unboundid.ldap.sdk.unboundidds.controls.
107            GetEffectiveRightsRequestControl;
108import com.unboundid.ldap.sdk.unboundidds.controls.
109            GetPasswordPolicyStateIssuesRequestControl;
110import com.unboundid.ldap.sdk.unboundidds.controls.
111            GetPasswordPolicyStateIssuesResponseControl;
112import com.unboundid.ldap.sdk.unboundidds.controls.
113            GetRecentLoginHistoryRequestControl;
114import com.unboundid.ldap.sdk.unboundidds.controls.
115            GetRecentLoginHistoryResponseControl;
116import com.unboundid.ldap.sdk.unboundidds.controls.GetServerIDRequestControl;
117import com.unboundid.ldap.sdk.unboundidds.controls.GetServerIDResponseControl;
118import com.unboundid.ldap.sdk.unboundidds.controls.
119            GetUserResourceLimitsRequestControl;
120import com.unboundid.ldap.sdk.unboundidds.controls.
121            GetUserResourceLimitsResponseControl;
122import com.unboundid.ldap.sdk.unboundidds.controls.HardDeleteRequestControl;
123import com.unboundid.ldap.sdk.unboundidds.controls.
124            IgnoreNoUserModificationRequestControl;
125import com.unboundid.ldap.sdk.unboundidds.controls.
126            IntermediateClientRequestControl;
127import com.unboundid.ldap.sdk.unboundidds.controls.
128            IntermediateClientResponseControl;
129import com.unboundid.ldap.sdk.unboundidds.controls.JSONFormattedRequestControl;
130import com.unboundid.ldap.sdk.unboundidds.controls.JSONFormattedResponseControl;
131import com.unboundid.ldap.sdk.unboundidds.controls.JoinRequestControl;
132import com.unboundid.ldap.sdk.unboundidds.controls.JoinResultControl;
133import com.unboundid.ldap.sdk.unboundidds.controls.
134            MatchingEntryCountRequestControl;
135import com.unboundid.ldap.sdk.unboundidds.controls.
136            MatchingEntryCountResponseControl;
137import com.unboundid.ldap.sdk.unboundidds.controls.
138            NameWithEntryUUIDRequestControl;
139import com.unboundid.ldap.sdk.unboundidds.controls.NoOpRequestControl;
140import com.unboundid.ldap.sdk.unboundidds.controls.
141            OperationPurposeRequestControl;
142import com.unboundid.ldap.sdk.unboundidds.controls.
143            OverrideSearchLimitsRequestControl;
144import com.unboundid.ldap.sdk.unboundidds.controls.PasswordPolicyRequestControl;
145import com.unboundid.ldap.sdk.unboundidds.controls.
146            PasswordPolicyResponseControl;
147import com.unboundid.ldap.sdk.unboundidds.controls.
148            PasswordUpdateBehaviorRequestControl;
149import com.unboundid.ldap.sdk.unboundidds.controls.
150            PasswordValidationDetailsRequestControl;
151import com.unboundid.ldap.sdk.unboundidds.controls.
152            PasswordValidationDetailsResponseControl;
153import com.unboundid.ldap.sdk.unboundidds.controls.
154            PermitUnindexedSearchRequestControl;
155import com.unboundid.ldap.sdk.unboundidds.controls.PurgePasswordRequestControl;
156import com.unboundid.ldap.sdk.unboundidds.controls.
157            RealAttributesOnlyRequestControl;
158import com.unboundid.ldap.sdk.unboundidds.controls.
159            RejectUnindexedSearchRequestControl;
160import com.unboundid.ldap.sdk.unboundidds.controls.
161            ReplicationRepairRequestControl;
162import com.unboundid.ldap.sdk.unboundidds.controls.RetainIdentityRequestControl;
163import com.unboundid.ldap.sdk.unboundidds.controls.RetirePasswordRequestControl;
164import com.unboundid.ldap.sdk.unboundidds.controls.
165            ReturnConflictEntriesRequestControl;
166import com.unboundid.ldap.sdk.unboundidds.controls.
167            RouteToBackendSetRequestControl;
168import com.unboundid.ldap.sdk.unboundidds.controls.RouteToServerRequestControl;
169import com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteResponseControl;
170import com.unboundid.ldap.sdk.unboundidds.controls.
171            SoftDeletedEntryAccessRequestControl;
172import com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteRequestControl;
173import com.unboundid.ldap.sdk.unboundidds.controls.
174            SuppressOperationalAttributeUpdateRequestControl;
175import com.unboundid.ldap.sdk.unboundidds.controls.
176            SuppressReferentialIntegrityUpdatesRequestControl;
177import com.unboundid.ldap.sdk.unboundidds.controls.UndeleteRequestControl;
178import com.unboundid.ldap.sdk.unboundidds.controls.UniquenessRequestControl;
179import com.unboundid.ldap.sdk.unboundidds.controls.UniquenessResponseControl;
180import com.unboundid.ldap.sdk.unboundidds.controls.
181            UnsolicitedCancelResponseControl;
182import com.unboundid.ldap.sdk.unboundidds.controls.
183            VirtualAttributesOnlyRequestControl;
184import com.unboundid.util.Base64;
185import com.unboundid.util.Debug;
186import com.unboundid.util.Extensible;
187import com.unboundid.util.NotMutable;
188import com.unboundid.util.NotNull;
189import com.unboundid.util.Nullable;
190import com.unboundid.util.StaticUtils;
191import com.unboundid.util.ThreadSafety;
192import com.unboundid.util.ThreadSafetyLevel;
193import com.unboundid.util.Validator;
194import com.unboundid.util.json.JSONBoolean;
195import com.unboundid.util.json.JSONObject;
196import com.unboundid.util.json.JSONString;
197import com.unboundid.util.json.JSONValue;
198
199import static com.unboundid.ldap.sdk.LDAPMessages.*;
200
201
202
203/**
204 * This class provides a data structure that represents an LDAP control.  A
205 * control is an element that may be attached to an LDAP request or response
206 * to provide additional information about the processing that should be (or has
207 * been) performed.  This class may be overridden to provide additional
208 * processing for specific types of controls.
209 * <BR><BR>
210 * A control includes the following elements:
211 * <UL>
212 *   <LI>An object identifier (OID), which identifies the type of control.</LI>
213 *   <LI>A criticality flag, which indicates whether the control should be
214 *       considered critical to the processing of the operation.  If a control
215 *       is marked critical but the server either does not support that control
216 *       or it is not appropriate for the associated request, then the server
217 *       will reject the request.  If a control is not marked critical and the
218 *       server either does not support it or it is not appropriate for the
219 *       associated request, then the server will simply ignore that
220 *       control and process the request as if it were not present.</LI>
221 *   <LI>An optional value, which provides additional information for the
222 *       control.  Some controls do not take values, and the value encoding for
223 *       controls which do take values varies based on the type of control.</LI>
224 * </UL>
225 * Controls may be included in a request from the client to the server, as well
226 * as responses from the server to the client (including intermediate response,
227 * search result entry, and search result references, in addition to the final
228 * response message for an operation).  When using request controls, they may be
229 * included in the request object at the time it is created, or may be added
230 * after the fact for {@link UpdatableLDAPRequest} objects.  When using
231 * response controls, each response control class includes a {@code get} method
232 * that can be used to extract the appropriate control from an appropriate
233 * result (e.g.,  {@link LDAPResult}, {@link SearchResultEntry}, or
234 * {@link SearchResultReference}).
235 */
236@Extensible()
237@NotMutable()
238@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
239public class Control
240       implements Serializable
241{
242  /**
243   * The BER type to use for the encoded set of controls in an LDAP message.
244   */
245  private static final byte CONTROLS_TYPE = (byte) 0xA0;
246
247
248
249  /**
250   * A map of the decodable control classes that have been registered with the
251   * LDAP SDK, mapped from OID to fully-qualified class name.
252   */
253  @NotNull static final ConcurrentHashMap<String,String>
254       DECODEABLE_CONTROL_CLASS_NAMES = new ConcurrentHashMap<>();
255
256
257
258  /**
259   * A map of the instantiated decodeable control classes registered with the
260   * LDAP SDK, mapped from OID to class instance.
261   */
262  @NotNull private static final ConcurrentHashMap<String,DecodeableControl>
263       DECODEABLE_CONTROL_INSTANCES = new ConcurrentHashMap<>();
264
265
266
267  /**
268   * The serial version UID for this serializable class.
269   */
270  private static final long serialVersionUID = 4440956109070220054L;
271
272
273
274  // The encoded value for this control, if there is one.
275  @Nullable private final ASN1OctetString value;
276
277  // Indicates whether this control should be considered critical.
278  private final boolean isCritical;
279
280  // The OID for this control
281  @NotNull private final String oid;
282
283
284
285  static
286  {
287    com.unboundid.ldap.sdk.controls.ControlHelper.
288         registerDefaultResponseControls();
289    com.unboundid.ldap.sdk.experimental.ControlHelper.
290         registerDefaultResponseControls();
291    com.unboundid.ldap.sdk.unboundidds.controls.ControlHelper.
292         registerDefaultResponseControls();
293  }
294
295
296
297  /**
298   * Creates a new empty control instance that is intended to be used only for
299   * decoding controls via the {@code DecodeableControl} interface.  All
300   * {@code DecodeableControl} objects must provide a default constructor that
301   * can be used to create an instance suitable for invoking the
302   * {@code decodeControl} method.
303   */
304  protected Control()
305  {
306    oid        = null;
307    isCritical = true;
308    value      = null;
309  }
310
311
312
313  /**
314   * Creates a new control whose fields are initialized from the contents of the
315   * provided control.
316   *
317   * @param  control  The control whose information should be used to create
318   *                  this new control.
319   */
320  protected Control(@NotNull final Control control)
321  {
322    oid        = control.oid;
323    isCritical = control.isCritical;
324    value      = control.value;
325  }
326
327
328
329  /**
330   * Creates a new control with the provided OID.  It will not be critical, and
331   * it will not have a value.
332   *
333   * @param  oid  The OID for this control.  It must not be {@code null}.
334   */
335  public Control(@NotNull final String oid)
336  {
337    Validator.ensureNotNull(oid);
338
339    this.oid   = oid;
340    isCritical = false;
341    value      = null;
342  }
343
344
345
346  /**
347   * Creates a new control with the provided OID and criticality.  It will not
348   * have a value.
349   *
350   * @param  oid         The OID for this control.  It must not be {@code null}.
351   * @param  isCritical  Indicates whether this control should be considered
352   *                     critical.
353   */
354  public Control(@NotNull final String oid, final boolean isCritical)
355  {
356    Validator.ensureNotNull(oid);
357
358    this.oid        = oid;
359    this.isCritical = isCritical;
360    value           = null;
361  }
362
363
364
365  /**
366   * Creates a new control with the provided information.
367   *
368   * @param  oid         The OID for this control.  It must not be {@code null}.
369   * @param  isCritical  Indicates whether this control should be considered
370   *                     critical.
371   * @param  value       The value for this control.  It may be {@code null} if
372   *                     there is no value.
373   */
374  public Control(@NotNull final String oid, final boolean isCritical,
375                 @Nullable final ASN1OctetString value)
376  {
377    Validator.ensureNotNull(oid);
378
379    this.oid        = oid;
380    this.isCritical = isCritical;
381    this.value      = value;
382  }
383
384
385
386  /**
387   * Retrieves the OID for this control.
388   *
389   * @return  The OID for this control.
390   */
391  @NotNull()
392  public final String getOID()
393  {
394    return oid;
395  }
396
397
398
399  /**
400   * Indicates whether this control should be considered critical.
401   *
402   * @return  {@code true} if this control should be considered critical, or
403   *          {@code false} if not.
404   */
405  public final boolean isCritical()
406  {
407    return isCritical;
408  }
409
410
411
412  /**
413   * Indicates whether this control has a value.
414   *
415   * @return  {@code true} if this control has a value, or {@code false} if not.
416   */
417  public final boolean hasValue()
418  {
419    return (value != null);
420  }
421
422
423
424  /**
425   * Retrieves the encoded value for this control.
426   *
427   * @return  The encoded value for this control, or {@code null} if there is no
428   *          value.
429   */
430  @Nullable()
431  public final ASN1OctetString getValue()
432  {
433    return value;
434  }
435
436
437
438  /**
439   * Writes an ASN.1-encoded representation of this control to the provided
440   * ASN.1 stream writer.
441   *
442   * @param  writer  The ASN.1 stream writer to which the encoded representation
443   *                 should be written.
444   */
445  public final void writeTo(@NotNull final ASN1Buffer writer)
446  {
447    final ASN1BufferSequence controlSequence = writer.beginSequence();
448    writer.addOctetString(oid);
449
450    if (isCritical)
451    {
452      writer.addBoolean(true);
453    }
454
455    if (value != null)
456    {
457      writer.addOctetString(value.getValue());
458    }
459
460    controlSequence.end();
461  }
462
463
464
465  /**
466   * Encodes this control to an ASN.1 sequence suitable for use in an LDAP
467   * message.
468   *
469   * @return  The encoded representation of this control.
470   */
471  @NotNull()
472  public final ASN1Sequence encode()
473  {
474    final ArrayList<ASN1Element> elementList = new ArrayList<>(3);
475    elementList.add(new ASN1OctetString(oid));
476
477    if (isCritical)
478    {
479      elementList.add(new ASN1Boolean(isCritical));
480    }
481
482    if (value != null)
483    {
484      elementList.add(new ASN1OctetString(value.getValue()));
485    }
486
487    return new ASN1Sequence(elementList);
488  }
489
490
491
492  /**
493   * Reads an LDAP control from the provided ASN.1 stream reader.
494   *
495   * @param  reader  The ASN.1 stream reader from which to read the control.
496   *
497   * @return  The decoded control.
498   *
499   * @throws  LDAPException  If a problem occurs while attempting to read or
500   *                         parse the control.
501   */
502  @NotNull()
503  public static Control readFrom(@NotNull final ASN1StreamReader reader)
504         throws LDAPException
505  {
506    try
507    {
508      final ASN1StreamReaderSequence controlSequence = reader.beginSequence();
509      final String oid = reader.readString();
510
511      boolean isCritical = false;
512      ASN1OctetString value = null;
513      while (controlSequence.hasMoreElements())
514      {
515        final byte type = (byte) reader.peek();
516        switch (type)
517        {
518          case ASN1Constants.UNIVERSAL_BOOLEAN_TYPE:
519            isCritical = reader.readBoolean();
520            break;
521          case ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE:
522            value = new ASN1OctetString(reader.readBytes());
523            break;
524          default:
525            throw new LDAPException(ResultCode.DECODING_ERROR,
526                 ERR_CONTROL_INVALID_TYPE.get(StaticUtils.toHex(type)));
527        }
528      }
529
530      return decode(oid, isCritical, value);
531    }
532    catch (final LDAPException le)
533    {
534      Debug.debugException(le);
535      throw le;
536    }
537    catch (final Exception e)
538    {
539      Debug.debugException(e);
540      throw new LDAPException(ResultCode.DECODING_ERROR,
541           ERR_CONTROL_CANNOT_DECODE.get(StaticUtils.getExceptionMessage(e)),
542           e);
543    }
544  }
545
546
547
548  /**
549   * Decodes the provided ASN.1 sequence as an LDAP control.
550   *
551   * @param  controlSequence  The ASN.1 sequence to be decoded.
552   *
553   * @return  The decoded control.
554   *
555   * @throws  LDAPException  If a problem occurs while attempting to decode the
556   *                         provided ASN.1 sequence as an LDAP control.
557   */
558  @NotNull()
559  public static Control decode(@NotNull final ASN1Sequence controlSequence)
560         throws LDAPException
561  {
562    final ASN1Element[] elements = controlSequence.elements();
563
564    if ((elements.length < 1) || (elements.length > 3))
565    {
566      throw new LDAPException(ResultCode.DECODING_ERROR,
567                              ERR_CONTROL_DECODE_INVALID_ELEMENT_COUNT.get(
568                                   elements.length));
569    }
570
571    final String oid =
572         ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
573
574    boolean isCritical = false;
575    ASN1OctetString value = null;
576    if (elements.length == 2)
577    {
578      switch (elements[1].getType())
579      {
580        case ASN1Constants.UNIVERSAL_BOOLEAN_TYPE:
581          try
582          {
583            isCritical =
584                 ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue();
585          }
586          catch (final ASN1Exception ae)
587          {
588            Debug.debugException(ae);
589            throw new LDAPException(ResultCode.DECODING_ERROR,
590                 ERR_CONTROL_DECODE_CRITICALITY.get(
591                      StaticUtils.getExceptionMessage(ae)),
592                 ae);
593          }
594          break;
595
596        case ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE:
597          value = ASN1OctetString.decodeAsOctetString(elements[1]);
598          break;
599
600        default:
601          throw new LDAPException(ResultCode.DECODING_ERROR,
602               ERR_CONTROL_INVALID_TYPE.get(
603                    StaticUtils.toHex(elements[1].getType())));
604      }
605    }
606    else if (elements.length == 3)
607    {
608      try
609      {
610        isCritical = ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue();
611      }
612      catch (final ASN1Exception ae)
613      {
614        Debug.debugException(ae);
615        throw new LDAPException(ResultCode.DECODING_ERROR,
616             ERR_CONTROL_DECODE_CRITICALITY.get(
617                  StaticUtils.getExceptionMessage(ae)),
618             ae);
619      }
620
621      value = ASN1OctetString.decodeAsOctetString(elements[2]);
622    }
623
624    return decode(oid, isCritical, value);
625  }
626
627
628
629  /**
630   * Attempts to create the most appropriate control instance from the provided
631   * information.  If a {@link DecodeableControl} instance has been registered
632   * for the specified OID, then this method will attempt to use that instance
633   * to construct a control.  If that fails, or if no appropriate
634   * {@code DecodeableControl} is registered, then a generic control will be
635   * returned.
636   *
637   * @param  oid         The OID for the control.  It must not be {@code null}.
638   * @param  isCritical  Indicates whether the control should be considered
639   *                     critical.
640   * @param  value       The value for the control.  It may be {@code null} if
641   *                     there is no value.
642   *
643   * @return  The decoded control.
644   *
645   * @throws  LDAPException  If a problem occurs while attempting to decode the
646   *                         provided ASN.1 sequence as an LDAP control.
647   */
648  @NotNull()
649  public static Control decode(@NotNull final String oid,
650                               final boolean isCritical,
651                               @Nullable final ASN1OctetString value)
652         throws LDAPException
653  {
654    DecodeableControl decodeableControl = DECODEABLE_CONTROL_INSTANCES.get(oid);
655    if (decodeableControl == null)
656    {
657      final String controlClassName = DECODEABLE_CONTROL_CLASS_NAMES.get(oid);
658      if (controlClassName == null)
659      {
660        return new Control(oid, isCritical, value);
661      }
662
663      try
664      {
665        final Class<?> controlClass = Class.forName(controlClassName);
666        final Constructor<?> noArgumentConstructor =
667             controlClass.getDeclaredConstructor();
668        noArgumentConstructor.setAccessible(true);
669        decodeableControl =
670             (DecodeableControl) noArgumentConstructor.newInstance();
671      }
672      catch (final Exception e)
673      {
674        Debug.debugException(e);
675        return new Control(oid, isCritical, value);
676      }
677    }
678
679    try
680    {
681      return decodeableControl.decodeControl(oid, isCritical, value);
682    }
683    catch (final Exception e)
684    {
685      Debug.debugException(e);
686      return new Control(oid, isCritical, value);
687    }
688  }
689
690
691
692  /**
693   * Encodes the provided set of controls to an ASN.1 sequence suitable for
694   * inclusion in an LDAP message.
695   *
696   * @param  controls  The set of controls to be encoded.
697   *
698   * @return  An ASN.1 sequence containing the encoded set of controls.
699   */
700  @NotNull()
701  public static ASN1Sequence encodeControls(@NotNull final Control[] controls)
702  {
703    final ASN1Sequence[] controlElements = new ASN1Sequence[controls.length];
704    for (int i=0; i < controls.length; i++)
705    {
706      controlElements[i] = controls[i].encode();
707    }
708
709    return new ASN1Sequence(CONTROLS_TYPE, controlElements);
710  }
711
712
713
714  /**
715   * Decodes the contents of the provided sequence as a set of controls.
716   *
717   * @param  controlSequence  The ASN.1 sequence containing the encoded set of
718   *                          controls.
719   *
720   * @return  The decoded set of controls.
721   *
722   * @throws  LDAPException  If a problem occurs while attempting to decode any
723   *                         of the controls.
724   */
725  @NotNull()
726  public static Control[] decodeControls(
727                               @NotNull final ASN1Sequence controlSequence)
728         throws LDAPException
729  {
730    final ASN1Element[] controlElements = controlSequence.elements();
731    final Control[] controls = new Control[controlElements.length];
732
733    for (int i=0; i < controlElements.length; i++)
734    {
735      try
736      {
737        controls[i] = decode(ASN1Sequence.decodeAsSequence(controlElements[i]));
738      }
739      catch (final ASN1Exception ae)
740      {
741        Debug.debugException(ae);
742        throw new LDAPException(ResultCode.DECODING_ERROR,
743             ERR_CONTROLS_DECODE_ELEMENT_NOT_SEQUENCE.get(
744                  StaticUtils.getExceptionMessage(ae)),
745             ae);
746      }
747    }
748
749    return controls;
750  }
751
752
753
754  /**
755   * Registers the specified class to be used in an attempt to decode controls
756   * with the specified OID.
757   *
758   * @param  oid        The response control OID for which the provided class
759   *                    will be registered.
760   * @param  className  The fully-qualified name for the Java class that
761   *                    provides the decodeable control implementation to use
762   *                    for the provided OID.
763   */
764  public static void registerDecodeableControl(@NotNull final String oid,
765                                               @NotNull final String className)
766  {
767    DECODEABLE_CONTROL_CLASS_NAMES.put(oid, className);
768    DECODEABLE_CONTROL_INSTANCES.remove(oid);
769  }
770
771
772
773  /**
774   * Registers the provided class to be used in an attempt to decode controls
775   * with the specified OID.
776   *
777   * @param  oid              The response control OID for which the provided
778   *                          class will be registered.
779   * @param  controlInstance  The control instance that should be used to decode
780   *                          controls with the provided OID.
781   */
782  public static void registerDecodeableControl(@NotNull final String oid,
783                          @NotNull final DecodeableControl controlInstance)
784  {
785    DECODEABLE_CONTROL_CLASS_NAMES.put(oid,
786         controlInstance.getClass().getName());
787    DECODEABLE_CONTROL_INSTANCES.put(oid, controlInstance);
788  }
789
790
791
792  /**
793   * Deregisters the decodeable control class associated with the provided OID.
794   *
795   * @param  oid  The response control OID for which to deregister the
796   *              decodeable control class.
797   */
798  public static void deregisterDecodeableControl(@NotNull final String oid)
799  {
800    DECODEABLE_CONTROL_CLASS_NAMES.remove(oid);
801    DECODEABLE_CONTROL_INSTANCES.remove(oid);
802  }
803
804
805
806  /**
807   * Retrieves a hash code for this control.
808   *
809   * @return  A hash code for this control.
810   */
811  @Override()
812  public final int hashCode()
813  {
814    int hashCode = oid.hashCode();
815
816    if (isCritical)
817    {
818      hashCode++;
819    }
820
821    if (value != null)
822    {
823      hashCode += value.hashCode();
824    }
825
826    return hashCode;
827  }
828
829
830
831  /**
832   * Indicates whether the provided object may be considered equal to this
833   * control.
834   *
835   * @param  o  The object for which to make the determination.
836   *
837   * @return  {@code true} if the provided object may be considered equal to
838   *          this control, or {@code false} if not.
839   */
840  @Override()
841  public final boolean equals(@Nullable final Object o)
842  {
843    if (o == null)
844    {
845      return false;
846    }
847
848    if (o == this)
849    {
850      return true;
851    }
852
853    if (! (o instanceof Control))
854    {
855      return false;
856    }
857
858    final Control c = (Control) o;
859    if (! oid.equals(c.oid))
860    {
861      return false;
862    }
863
864    if (isCritical != c.isCritical)
865    {
866      return false;
867    }
868
869    if (value == null)
870    {
871      if (c.value != null)
872      {
873        return false;
874      }
875    }
876    else
877    {
878      if (c.value == null)
879      {
880        return false;
881      }
882
883      if (! value.equals(c.value))
884      {
885        return false;
886      }
887    }
888
889
890    return true;
891  }
892
893
894
895  /**
896   * Retrieves the user-friendly name for this control, if available.  If no
897   * user-friendly name has been defined, then the OID will be returned.
898   *
899   * @return  The user-friendly name for this control, or the OID if no
900   *          user-friendly name is available.
901   */
902  @NotNull()
903  public String getControlName()
904  {
905    // By default, we will return the OID.  Subclasses should override this to
906    // provide the user-friendly name.
907    return oid;
908  }
909
910
911
912  /**
913   * Retrieves a representation of this control as a JSON object.  The JSON
914   * object uses the following fields:
915   * <UL>
916   *   <LI>
917   *     {@code oid} -- A mandatory string field whose value is the object
918   *     identifier for this control.
919   *   </LI>
920   *   <LI>
921   *     {@code control-name} -- An optional string field whose value is a
922   *     human-readable name for this control.  This field is only intended for
923   *     descriptive purposes, and when decoding a control, the {@code oid}
924   *     field should be used to identify the type of control.
925   *   </LI>
926   *   <LI>
927   *     {@code criticality} -- A mandatory Boolean field used to indicate
928   *     whether this control is considered critical.
929   *   </LI>
930   *   <LI>
931   *     {@code value-base64} -- An optional string field whose value is a
932   *     base64-encoded representation of the raw value for this control.  At
933   *     most one of the {@code value-base64} and {@code value-json} fields may
934   *     be present, and both fields will be absent for controls that do not
935   *     have a value.
936   *   </LI>
937   *   <LI>
938   *     {@code value-json} -- An optional JSON object field whose value is a
939   *     user-friendly, control-specific representation of the value for this
940   *     control.  This representation of the value is only available for
941   *     certain types of controls, and subclasses will override this method to
942   *     provide an appropriate representation of that value, and their Javadoc
943   *     documentation will describe the fields that may be present in the
944   *     value.  At most one of the  {@code value-base64} and {@code value-json}
945   *     fields may be present, and both fields will be absent for controls that
946   *     do not have a value.
947   *   </LI>
948   * </UL>
949   *
950   * @return  A JSON object that contains a representation of this control.
951   */
952  @NotNull()
953  public JSONObject toJSONControl()
954  {
955    final Map<String,JSONValue> fields = new LinkedHashMap<>(
956         StaticUtils.computeMapCapacity(4));
957
958    fields.put(JSONControlDecodeHelper.JSON_FIELD_OID, new JSONString(oid));
959
960    final String name = getControlName();
961    if ((name != null) && (! name.equals(oid)))
962    {
963      fields.put(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME,
964           new JSONString(name));
965    }
966
967    fields.put(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY,
968         new JSONBoolean(isCritical));
969
970    if (value != null)
971    {
972      fields.put(JSONControlDecodeHelper.JSON_FIELD_VALUE_BASE64,
973           new JSONString(Base64.encode(value.getValue())));
974    }
975
976    return new JSONObject(fields);
977  }
978
979
980
981  /**
982   * Attempts to decode the provided object as a JSON representation of a
983   * control.  If the OID extracted from the provided JSON object matches the
984   * OID for a control with a known-supported encoding, then control-specific
985   * decoding will be used to allow for a more user-friendly version of the
986   * object (for example, with a value formatted as a JSON object rather than
987   * raw base64-encoded data).  If no specific support is available for the
988   * specified control, then a more generic decoding will be used, and only
989   * base64-encoded values will be supported.
990   *
991   * @param  controlObject     The JSON object to be decoded.  It must not be
992   *                           {@code null}.
993   * @param  strict            Indicates whether to use strict mode when
994   *                           decoding the provided JSON object.  If this is
995   *                           {@code true}, then this method will throw an
996   *                           exception if the provided JSON object contains
997   *                           any unrecognized fields, and potentially if any
998   *                           other constraints are violated.  If this is
999   *                           {@code false}, then unrecognized fields will be
1000   *                           ignored, and potentially other lenient parsing
1001   *                           will be used.
1002   * @param  isRequestControl  Indicates whether the provided JSON object
1003   *                           represents a request control (if {@code true})
1004   *                           rather than a response control
1005   *                           (if {@code false}).  This will be used in cases
1006   *                           where both a request and response control of the
1007   *                           same type share the same OID.
1008   *
1009   * @return  The control that was decoded from the provided JSON object.
1010   *
1011   * @throws  LDAPException  If the provided JSON object cannot be parsed as a
1012   *                         valid control.
1013   */
1014  @NotNull()
1015  public static Control decodeJSONControl(
1016              @NotNull final JSONObject controlObject,
1017              final boolean strict,
1018              final boolean isRequestControl)
1019         throws LDAPException
1020  {
1021    final String oid = controlObject.getFieldAsString(
1022         JSONControlDecodeHelper.JSON_FIELD_OID);
1023    if (oid == null)
1024    {
1025      throw new LDAPException(ResultCode.DECODING_ERROR,
1026           ERR_CONTROL_JSON_OBJECT_MISSING_OID.get(
1027                controlObject.toSingleLineString(),
1028                JSONControlDecodeHelper.JSON_FIELD_OID));
1029    }
1030
1031    switch (oid)
1032    {
1033      case AccessLogFieldRequestControl.ACCESS_LOG_FIELD_REQUEST_OID:
1034        return AccessLogFieldRequestControl.decodeJSONControl(
1035             controlObject, strict);
1036
1037      // NOTE:  The account usable request and response controls use the same
1038      // OID.
1039      case AccountUsableRequestControl.ACCOUNT_USABLE_REQUEST_OID:
1040        if (isRequestControl)
1041        {
1042          return AccountUsableRequestControl.decodeJSONControl(
1043               controlObject, strict);
1044        }
1045        else
1046        {
1047          return AccountUsableResponseControl.decodeJSONControl(
1048               controlObject, strict);
1049        }
1050
1051      case AdministrativeOperationRequestControl.
1052           ADMINISTRATIVE_OPERATION_REQUEST_OID:
1053        return AdministrativeOperationRequestControl.decodeJSONControl(
1054             controlObject, strict);
1055
1056      case AssertionRequestControl.ASSERTION_REQUEST_OID:
1057        return AssertionRequestControl.decodeJSONControl(controlObject, strict);
1058
1059      case AssuredReplicationRequestControl.ASSURED_REPLICATION_REQUEST_OID:
1060        return AssuredReplicationRequestControl.decodeJSONControl(
1061             controlObject, strict);
1062
1063      case AssuredReplicationResponseControl.ASSURED_REPLICATION_RESPONSE_OID:
1064        return AssuredReplicationResponseControl.decodeJSONControl(
1065             controlObject, strict);
1066
1067      case AuthorizationIdentityRequestControl.
1068           AUTHORIZATION_IDENTITY_REQUEST_OID:
1069        return AuthorizationIdentityRequestControl.decodeJSONControl(
1070             controlObject, strict);
1071
1072      case AuthorizationIdentityResponseControl.
1073           AUTHORIZATION_IDENTITY_RESPONSE_OID:
1074        return AuthorizationIdentityResponseControl.decodeJSONControl(
1075             controlObject, strict);
1076
1077      case DraftLDUPSubentriesRequestControl.SUBENTRIES_REQUEST_OID:
1078        return DraftLDUPSubentriesRequestControl.decodeJSONControl(
1079             controlObject, strict);
1080
1081      case ExcludeBranchRequestControl.EXCLUDE_BRANCH_REQUEST_OID:
1082        return ExcludeBranchRequestControl.decodeJSONControl(
1083             controlObject, strict);
1084
1085      case ExtendedSchemaInfoRequestControl.EXTENDED_SCHEMA_INFO_REQUEST_OID:
1086        return ExtendedSchemaInfoRequestControl.decodeJSONControl(
1087             controlObject, strict);
1088
1089      case GenerateAccessTokenRequestControl.GENERATE_ACCESS_TOKEN_REQUEST_OID:
1090        return GenerateAccessTokenRequestControl.decodeJSONControl(
1091             controlObject, strict);
1092
1093      case GenerateAccessTokenResponseControl.
1094           GENERATE_ACCESS_TOKEN_RESPONSE_OID:
1095        return GenerateAccessTokenResponseControl.decodeJSONControl(
1096             controlObject, strict);
1097
1098      case GeneratePasswordRequestControl.GENERATE_PASSWORD_REQUEST_OID:
1099        return GeneratePasswordRequestControl.decodeJSONControl(
1100             controlObject, strict);
1101
1102      case GeneratePasswordResponseControl.GENERATE_PASSWORD_RESPONSE_OID:
1103        return GeneratePasswordResponseControl.decodeJSONControl(
1104             controlObject, strict);
1105
1106      // NOTE:  The get authorization entry request and response controls use
1107      // the same OID.
1108      case GetAuthorizationEntryRequestControl.
1109           GET_AUTHORIZATION_ENTRY_REQUEST_OID:
1110        if (isRequestControl)
1111        {
1112          return GetAuthorizationEntryRequestControl.decodeJSONControl(
1113               controlObject, strict);
1114        }
1115        else
1116        {
1117          return GetAuthorizationEntryResponseControl.decodeJSONControl(
1118               controlObject, strict);
1119        }
1120
1121      case GetBackendSetIDRequestControl.GET_BACKEND_SET_ID_REQUEST_OID:
1122        return GetBackendSetIDRequestControl.decodeJSONControl(
1123             controlObject, strict);
1124
1125      case GetBackendSetIDResponseControl.GET_BACKEND_SET_ID_RESPONSE_OID:
1126        return GetBackendSetIDResponseControl.decodeJSONControl(
1127             controlObject, strict);
1128
1129      case GetEffectiveRightsRequestControl.GET_EFFECTIVE_RIGHTS_REQUEST_OID:
1130        return GetEffectiveRightsRequestControl.decodeJSONControl(
1131             controlObject, strict);
1132
1133      case GetPasswordPolicyStateIssuesRequestControl.
1134           GET_PASSWORD_POLICY_STATE_ISSUES_REQUEST_OID:
1135        return GetPasswordPolicyStateIssuesRequestControl.decodeJSONControl(
1136             controlObject, strict);
1137
1138      case GetPasswordPolicyStateIssuesResponseControl.
1139           GET_PASSWORD_POLICY_STATE_ISSUES_RESPONSE_OID:
1140        return GetPasswordPolicyStateIssuesResponseControl.decodeJSONControl(
1141             controlObject, strict);
1142
1143      case GetRecentLoginHistoryRequestControl.
1144           GET_RECENT_LOGIN_HISTORY_REQUEST_OID:
1145        return GetRecentLoginHistoryRequestControl.decodeJSONControl(
1146             controlObject, strict);
1147
1148      case GetRecentLoginHistoryResponseControl.
1149           GET_RECENT_LOGIN_HISTORY_RESPONSE_OID:
1150        return GetRecentLoginHistoryResponseControl.decodeJSONControl(
1151             controlObject, strict);
1152
1153      case GetServerIDRequestControl.GET_SERVER_ID_REQUEST_OID:
1154        return GetServerIDRequestControl.decodeJSONControl(
1155             controlObject, strict);
1156
1157      case GetServerIDResponseControl.GET_SERVER_ID_RESPONSE_OID:
1158        return GetServerIDResponseControl.decodeJSONControl(
1159             controlObject, strict);
1160
1161      case GetUserResourceLimitsRequestControl.
1162           GET_USER_RESOURCE_LIMITS_REQUEST_OID:
1163        return GetUserResourceLimitsRequestControl.decodeJSONControl(
1164             controlObject, strict);
1165
1166      case GetUserResourceLimitsResponseControl.
1167           GET_USER_RESOURCE_LIMITS_RESPONSE_OID:
1168        return GetUserResourceLimitsResponseControl.decodeJSONControl(
1169             controlObject, strict);
1170
1171      case HardDeleteRequestControl.HARD_DELETE_REQUEST_OID:
1172        return HardDeleteRequestControl.decodeJSONControl(
1173             controlObject, strict);
1174
1175      case IgnoreNoUserModificationRequestControl.
1176           IGNORE_NO_USER_MODIFICATION_REQUEST_OID:
1177        return IgnoreNoUserModificationRequestControl.decodeJSONControl(
1178             controlObject, strict);
1179
1180      // NOTE:  The intermediate client request and response controls use the
1181      // same OID.
1182      case IntermediateClientRequestControl.INTERMEDIATE_CLIENT_REQUEST_OID:
1183        if (isRequestControl)
1184        {
1185          return IntermediateClientRequestControl.decodeJSONControl(
1186               controlObject, strict);
1187        }
1188        else
1189        {
1190          return IntermediateClientResponseControl.decodeJSONControl(
1191               controlObject, strict);
1192        }
1193
1194      // NOTE:  The join request and result controls use the same OID.
1195      case JoinRequestControl.JOIN_REQUEST_OID:
1196        if (isRequestControl)
1197        {
1198          return JoinRequestControl.decodeJSONControl(controlObject, strict);
1199        }
1200        else
1201        {
1202          return JoinResultControl.decodeJSONControl(controlObject, strict);
1203        }
1204
1205      case JSONFormattedRequestControl.JSON_FORMATTED_REQUEST_OID:
1206        return JSONFormattedRequestControl.decodeJSONControl(
1207             controlObject, strict);
1208
1209      case JSONFormattedResponseControl.JSON_FORMATTED_RESPONSE_OID:
1210        return JSONFormattedResponseControl.decodeJSONControl(
1211             controlObject, strict);
1212
1213      case ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID:
1214        return ManageDsaITRequestControl.decodeJSONControl(
1215             controlObject, strict);
1216
1217      case MatchedValuesRequestControl.MATCHED_VALUES_REQUEST_OID:
1218        return MatchedValuesRequestControl.decodeJSONControl(
1219             controlObject, strict);
1220
1221      case MatchingEntryCountRequestControl.MATCHING_ENTRY_COUNT_REQUEST_OID:
1222        return MatchingEntryCountRequestControl.decodeJSONControl(
1223             controlObject, strict);
1224
1225      case MatchingEntryCountResponseControl.MATCHING_ENTRY_COUNT_RESPONSE_OID:
1226        return MatchingEntryCountResponseControl.decodeJSONControl(
1227             controlObject, strict);
1228
1229      case NameWithEntryUUIDRequestControl.NAME_WITH_ENTRY_UUID_REQUEST_OID:
1230        return NameWithEntryUUIDRequestControl.decodeJSONControl(
1231             controlObject, strict);
1232
1233      case NoOpRequestControl.NO_OP_REQUEST_OID:
1234        return NoOpRequestControl.decodeJSONControl(controlObject, strict);
1235
1236      case OperationPurposeRequestControl.OPERATION_PURPOSE_REQUEST_OID:
1237        return OperationPurposeRequestControl.decodeJSONControl(
1238             controlObject, strict);
1239
1240      case OverrideSearchLimitsRequestControl.
1241           OVERRIDE_SEARCH_LIMITS_REQUEST_OID:
1242        return OverrideSearchLimitsRequestControl.decodeJSONControl(
1243             controlObject, strict);
1244
1245      case PasswordExpiredControl.PASSWORD_EXPIRED_OID:
1246        return PasswordExpiredControl.decodeJSONControl(controlObject, strict);
1247
1248      case PasswordExpiringControl.PASSWORD_EXPIRING_OID:
1249        return PasswordExpiringControl.decodeJSONControl(controlObject, strict);
1250
1251      // NOTE:  The password policy request and result controls use the same
1252      // OID.
1253      case PasswordPolicyRequestControl.PASSWORD_POLICY_REQUEST_OID:
1254        if (isRequestControl)
1255        {
1256          return PasswordPolicyRequestControl.decodeJSONControl(
1257               controlObject, strict);
1258        }
1259        else
1260        {
1261          return PasswordPolicyResponseControl.decodeJSONControl(
1262               controlObject, strict);
1263        }
1264
1265      case PasswordUpdateBehaviorRequestControl.
1266           PASSWORD_UPDATE_BEHAVIOR_REQUEST_OID:
1267        return PasswordUpdateBehaviorRequestControl.decodeJSONControl(
1268             controlObject, strict);
1269
1270      case PasswordValidationDetailsRequestControl.
1271           PASSWORD_VALIDATION_DETAILS_REQUEST_OID:
1272        return PasswordValidationDetailsRequestControl.decodeJSONControl(
1273             controlObject, strict);
1274
1275      case PasswordValidationDetailsResponseControl.
1276           PASSWORD_VALIDATION_DETAILS_RESPONSE_OID:
1277        return PasswordValidationDetailsResponseControl.decodeJSONControl(
1278             controlObject, strict);
1279
1280      case PermissiveModifyRequestControl.PERMISSIVE_MODIFY_REQUEST_OID:
1281        return PermissiveModifyRequestControl.decodeJSONControl(
1282             controlObject, strict);
1283
1284      case PermitUnindexedSearchRequestControl.
1285           PERMIT_UNINDEXED_SEARCH_REQUEST_OID:
1286        return PermitUnindexedSearchRequestControl.decodeJSONControl(
1287             controlObject, strict);
1288
1289      // NOTE:  The post-read request and result controls use the same OID.
1290      case PostReadRequestControl.POST_READ_REQUEST_OID:
1291        if (isRequestControl)
1292        {
1293          return PostReadRequestControl.decodeJSONControl(
1294               controlObject, strict);
1295        }
1296        else
1297        {
1298          return PostReadResponseControl.decodeJSONControl(
1299               controlObject, strict);
1300        }
1301
1302      // NOTE:  The pre-read request and result controls use the same OID.
1303      case PreReadRequestControl.PRE_READ_REQUEST_OID:
1304        if (isRequestControl)
1305        {
1306          return PreReadRequestControl.decodeJSONControl(
1307               controlObject, strict);
1308        }
1309        else
1310        {
1311          return PreReadResponseControl.decodeJSONControl(
1312               controlObject, strict);
1313        }
1314
1315      case ProxiedAuthorizationV1RequestControl.
1316           PROXIED_AUTHORIZATION_V1_REQUEST_OID:
1317        return ProxiedAuthorizationV1RequestControl.decodeJSONControl(
1318             controlObject, strict);
1319
1320      case ProxiedAuthorizationV2RequestControl.
1321           PROXIED_AUTHORIZATION_V2_REQUEST_OID:
1322        return ProxiedAuthorizationV2RequestControl.decodeJSONControl(
1323             controlObject, strict);
1324
1325      case PurgePasswordRequestControl.PURGE_PASSWORD_REQUEST_OID:
1326        return PurgePasswordRequestControl.decodeJSONControl(
1327             controlObject, strict);
1328
1329      case RealAttributesOnlyRequestControl.REAL_ATTRIBUTES_ONLY_REQUEST_OID:
1330        return RealAttributesOnlyRequestControl.decodeJSONControl(
1331             controlObject, strict);
1332
1333      case RejectUnindexedSearchRequestControl.
1334           REJECT_UNINDEXED_SEARCH_REQUEST_OID:
1335        return RejectUnindexedSearchRequestControl.decodeJSONControl(
1336             controlObject, strict);
1337
1338      case ReplicationRepairRequestControl.REPLICATION_REPAIR_REQUEST_OID:
1339        return ReplicationRepairRequestControl.decodeJSONControl(
1340             controlObject, strict);
1341
1342      case RetainIdentityRequestControl.RETAIN_IDENTITY_REQUEST_OID:
1343        return RetainIdentityRequestControl.decodeJSONControl(
1344             controlObject, strict);
1345
1346      case RetirePasswordRequestControl.RETIRE_PASSWORD_REQUEST_OID:
1347        return RetirePasswordRequestControl.decodeJSONControl(
1348             controlObject, strict);
1349
1350      case ReturnConflictEntriesRequestControl.
1351           RETURN_CONFLICT_ENTRIES_REQUEST_OID:
1352        return ReturnConflictEntriesRequestControl.decodeJSONControl(
1353             controlObject, strict);
1354
1355      case RouteToBackendSetRequestControl.ROUTE_TO_BACKEND_SET_REQUEST_OID:
1356        return RouteToBackendSetRequestControl.decodeJSONControl(
1357             controlObject, strict);
1358
1359      case RouteToServerRequestControl.ROUTE_TO_SERVER_REQUEST_OID:
1360        return RouteToServerRequestControl.decodeJSONControl(
1361             controlObject, strict);
1362
1363      case ServerSideSortRequestControl.SERVER_SIDE_SORT_REQUEST_OID:
1364        return ServerSideSortRequestControl.decodeJSONControl(
1365             controlObject, strict);
1366
1367      case ServerSideSortResponseControl.SERVER_SIDE_SORT_RESPONSE_OID:
1368        return ServerSideSortResponseControl.decodeJSONControl(
1369             controlObject, strict);
1370
1371      case SimplePagedResultsControl.PAGED_RESULTS_OID:
1372        return SimplePagedResultsControl.decodeJSONControl(
1373             controlObject, strict);
1374
1375      case SoftDeletedEntryAccessRequestControl.
1376           SOFT_DELETED_ENTRY_ACCESS_REQUEST_OID:
1377        return SoftDeletedEntryAccessRequestControl.decodeJSONControl(
1378             controlObject, strict);
1379
1380      case SoftDeleteRequestControl.SOFT_DELETE_REQUEST_OID:
1381        return SoftDeleteRequestControl.decodeJSONControl(
1382             controlObject, strict);
1383
1384      case SoftDeleteResponseControl.SOFT_DELETE_RESPONSE_OID:
1385        return SoftDeleteResponseControl.decodeJSONControl(
1386             controlObject, strict);
1387
1388      case SubtreeDeleteRequestControl.SUBTREE_DELETE_REQUEST_OID:
1389        return SubtreeDeleteRequestControl.decodeJSONControl(
1390             controlObject, strict);
1391
1392      case SuppressOperationalAttributeUpdateRequestControl.
1393           SUPPRESS_OP_ATTR_UPDATE_REQUEST_OID:
1394        return SuppressOperationalAttributeUpdateRequestControl.
1395             decodeJSONControl(controlObject, strict);
1396
1397      case SuppressReferentialIntegrityUpdatesRequestControl.
1398           SUPPRESS_REFINT_REQUEST_OID:
1399        return SuppressReferentialIntegrityUpdatesRequestControl.
1400             decodeJSONControl(controlObject, strict);
1401
1402      case UndeleteRequestControl.UNDELETE_REQUEST_OID:
1403        return UndeleteRequestControl.decodeJSONControl(controlObject, strict);
1404
1405      case UniquenessRequestControl.UNIQUENESS_REQUEST_OID:
1406        return UniquenessRequestControl.decodeJSONControl(
1407             controlObject, strict);
1408
1409      case UniquenessResponseControl.UNIQUENESS_RESPONSE_OID:
1410        return UniquenessResponseControl.decodeJSONControl(
1411             controlObject, strict);
1412
1413      case UnsolicitedCancelResponseControl.UNSOLICITED_CANCEL_RESPONSE_OID:
1414        return UnsolicitedCancelResponseControl.decodeJSONControl(
1415             controlObject, strict);
1416
1417      case VirtualAttributesOnlyRequestControl.
1418           VIRTUAL_ATTRIBUTES_ONLY_REQUEST_OID:
1419        return VirtualAttributesOnlyRequestControl.decodeJSONControl(
1420             controlObject, strict);
1421
1422      case VirtualListViewRequestControl.VIRTUAL_LIST_VIEW_REQUEST_OID:
1423        return VirtualListViewRequestControl.decodeJSONControl(
1424             controlObject, strict);
1425
1426      case VirtualListViewResponseControl.VIRTUAL_LIST_VIEW_RESPONSE_OID:
1427        return VirtualListViewResponseControl.decodeJSONControl(
1428             controlObject, strict);
1429
1430      default:
1431        // The OID doesn't match that of a control for which we provide specific
1432        // JSON support.  Treat it as a generic control.  Note that we can't
1433        // support the JSON representation of the control value.
1434        final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper(
1435             controlObject, strict, true, false);
1436        if (jsonControl.getValueObject() != null)
1437        {
1438          throw new LDAPException(ResultCode.DECODING_ERROR,
1439               ERR_CONTROL_JSON_UNABLE_TO_SUPPORT_VALUE_JSON.get(
1440                    controlObject.toSingleLineString(),
1441                    JSONControlDecodeHelper.JSON_FIELD_VALUE_JSON, oid,
1442                    JSONControlDecodeHelper.JSON_FIELD_VALUE_BASE64));
1443        }
1444        else
1445        {
1446          return new Control(jsonControl.getOID(), jsonControl.getCriticality(),
1447               jsonControl.getRawValue());
1448        }
1449    }
1450  }
1451
1452
1453
1454  /**
1455   * Retrieves a string representation of this LDAP control.
1456   *
1457   * @return  A string representation of this LDAP control.
1458   */
1459  @Override()
1460  @NotNull()
1461  public String toString()
1462  {
1463    final StringBuilder buffer = new StringBuilder();
1464    toString(buffer);
1465    return buffer.toString();
1466  }
1467
1468
1469
1470  /**
1471   * Appends a string representation of this LDAP control to the provided
1472   * buffer.
1473   *
1474   * @param  buffer  The buffer to which to append the string representation of
1475   *                 this buffer.
1476   */
1477  public void toString(@NotNull final StringBuilder buffer)
1478  {
1479    buffer.append("Control(oid=");
1480    buffer.append(oid);
1481    buffer.append(", isCritical=");
1482    buffer.append(isCritical);
1483    buffer.append(", value=");
1484
1485    if (value == null)
1486    {
1487      buffer.append("{null}");
1488    }
1489    else
1490    {
1491      buffer.append("{byte[");
1492      buffer.append(value.getValue().length);
1493      buffer.append("]}");
1494    }
1495
1496    buffer.append(')');
1497  }
1498}