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}