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