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