001/* 002 * Copyright 2013-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2013-2024 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) 2013-2024 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.unboundidds.controls; 037 038 039 040import java.util.ArrayList; 041import java.util.LinkedHashMap; 042import java.util.List; 043import java.util.Map; 044 045import com.unboundid.asn1.ASN1Boolean; 046import com.unboundid.asn1.ASN1Element; 047import com.unboundid.asn1.ASN1Enumerated; 048import com.unboundid.asn1.ASN1Long; 049import com.unboundid.asn1.ASN1OctetString; 050import com.unboundid.asn1.ASN1Sequence; 051import com.unboundid.ldap.sdk.Control; 052import com.unboundid.ldap.sdk.JSONControlDecodeHelper; 053import com.unboundid.ldap.sdk.LDAPException; 054import com.unboundid.ldap.sdk.ResultCode; 055import com.unboundid.util.Debug; 056import com.unboundid.util.NotMutable; 057import com.unboundid.util.NotNull; 058import com.unboundid.util.Nullable; 059import com.unboundid.util.StaticUtils; 060import com.unboundid.util.ThreadSafety; 061import com.unboundid.util.ThreadSafetyLevel; 062import com.unboundid.util.json.JSONBoolean; 063import com.unboundid.util.json.JSONField; 064import com.unboundid.util.json.JSONNumber; 065import com.unboundid.util.json.JSONObject; 066import com.unboundid.util.json.JSONString; 067import com.unboundid.util.json.JSONValue; 068 069import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 070 071 072 073/** 074 * This class provides an implementation of an LDAP control that can be included 075 * in add, bind, modify, modify DN, and certain extended requests to indicate 076 * the level of replication assurance desired for the associated operation. 077 * <BR> 078 * <BLOCKQUOTE> 079 * <B>NOTE:</B> This class, and other classes within the 080 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 081 * supported for use against Ping Identity, UnboundID, and 082 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 083 * for proprietary functionality or for external specifications that are not 084 * considered stable or mature enough to be guaranteed to work in an 085 * interoperable way with other types of LDAP servers. 086 * </BLOCKQUOTE> 087 * <BR> 088 * The OID for this control is 1.3.6.1.4.1.30221.2.5.28, and it may have a 089 * criticality of either TRUE or FALSE. It must have a value with the following 090 * encoding: 091 * <PRE> 092 * AssuredReplicationRequest ::= SEQUENCE { 093 * minimumLocalLevel [0] LocalLevel OPTIONAL, 094 * maximumLocalLevel [1] LocalLevel OPTIONAL, 095 * minimumRemoteLevel [2] RemoteLevel OPTIONAL, 096 * maximumRemoteLevel [3] RemoteLevel OPTIONAL, 097 * timeoutMillis [4] INTEGER (1 .. 2147483647) OPTIONAL, 098 * sendResponseImmediately [5] BOOLEAN DEFAULT FALSE, 099 * ... } 100 * 101 * LocalLevel ::= ENUMERATED { 102 * none (0), 103 * receivedAnyServer (1), 104 * processedAllServers (2), 105 * ... } 106 * 107 * RemoteLevel ::= ENUMERATED { 108 * none (0), 109 * receivedAnyRemoteLocation (1), 110 * receivedAllRemoteLocations (2), 111 * processedAllRemoteServers (3), 112 * ... } 113 * </PRE> 114 * <BR><BR> 115 * <H2>Example</H2> 116 * The following example demonstrates the use of the assured replication request 117 * control in conjunction with a delete operation to request that the server not 118 * return the delete result to the client until the delete has been applied to 119 * all available servers in the local data center and has also been replicated 120 * to at least one remote data center: 121 * <PRE> 122 * DeleteRequest deleteRequest = new DeleteRequest( 123 * "uid=test.user,ou=People,dc=example,dc=com"); 124 * deleteRequest.addControl(new AssuredReplicationRequestControl( 125 * AssuredReplicationLocalLevel.PROCESSED_ALL_SERVERS, 126 * AssuredReplicationRemoteLevel.RECEIVED_ANY_REMOTE_LOCATION, 127 * 5000L)); 128 * LDAPResult deleteResult = connection.delete(deleteRequest); 129 * 130 * if (deleteResult.getResultCode() == ResultCode.SUCCESS) 131 * { 132 * AssuredReplicationResponseControl assuredReplicationResponse = 133 * AssuredReplicationResponseControl.get(deleteResult); 134 * if (assuredReplicationResponse == null) 135 * { 136 * // The entry was deleted, but its replication could not be confirmed in 137 * // either the local or remote data centers. 138 * } 139 * else 140 * { 141 * if (assuredReplicationResponse.localAssuranceSatisfied()) 142 * { 143 * if (assuredReplicationResponse.remoteAssuranceSatisfied()) 144 * { 145 * // The entry was deleted. The delete has been applied across all 146 * // available local servers, and has been replicated to at least one 147 * // remote data center. 148 * } 149 * else 150 * { 151 * // The entry was deleted. The delete has been applied across all 152 * // available local servers, but cannot be confirmed to have yet 153 * // been replicated to any remote data centers. 154 * } 155 * } 156 * else if (assuredReplicationResponse.remoteAssuranceSatisfied()) 157 * { 158 * // The entry was deleted. The delete has been confirmed to have been 159 * // replicated to at least one remote data center, but cannot be 160 * // confirmed to have yet been applied to all available local servers. 161 * } 162 * else 163 * { 164 * // The entry was deleted, but its replication could not be confirmed 165 * // to either local servers or remote data centers. 166 * } 167 * } 168 * } 169 * else 170 * { 171 * // The entry could not be deleted. 172 * } 173 * </PRE> 174 * 175 * @see AssuredReplicationResponseControl 176 */ 177@NotMutable() 178@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 179public final class AssuredReplicationRequestControl 180 extends Control 181{ 182 /** 183 * The OID (1.3.6.1.4.1.30221.2.5.28) for the assured replication request 184 * control. 185 */ 186 @NotNull public static final String ASSURED_REPLICATION_REQUEST_OID = 187 "1.3.6.1.4.1.30221.2.5.28"; 188 189 190 /** 191 * The BER type for the minimum local assurance level. 192 */ 193 private static final byte TYPE_MIN_LOCAL_LEVEL = (byte) 0x80; 194 195 196 /** 197 * The BER type for the maximum local assurance level. 198 */ 199 private static final byte TYPE_MAX_LOCAL_LEVEL = (byte) 0x81; 200 201 202 /** 203 * The BER type for the minimum remote assurance level. 204 */ 205 private static final byte TYPE_MIN_REMOTE_LEVEL = (byte) 0x82; 206 207 208 /** 209 * The BER type for the maximum remote assurance level. 210 */ 211 private static final byte TYPE_MAX_REMOTE_LEVEL = (byte) 0x83; 212 213 214 /** 215 * The BER type for the maximum remote assurance level. 216 */ 217 private static final byte TYPE_SEND_RESPONSE_IMMEDIATELY = (byte) 0x84; 218 219 220 /** 221 * The BER type for the timeout. 222 */ 223 private static final byte TYPE_TIMEOUT = (byte) 0x85; 224 225 226 227 /** 228 * The name of the field used to specify the maximum replication assurance 229 * level in the JSON representation of this control. 230 */ 231 @NotNull private static final String JSON_FIELD_MAXIMUM_LOCAL_LEVEL = 232 "maximum-local-level"; 233 234 235 236 /** 237 * The name of the field used to specify the maximum remote assurance 238 * level in the JSON representation of this control. 239 */ 240 @NotNull private static final String JSON_FIELD_MAXIMUM_REMOTE_LEVEL = 241 "maximum-remote-level"; 242 243 244 245 /** 246 * The name of the field used to specify the minimum replication assurance 247 * level in the JSON representation of this control. 248 */ 249 @NotNull private static final String JSON_FIELD_MINIMUM_LOCAL_LEVEL = 250 "minimum-local-level"; 251 252 253 254 /** 255 * The name of the field used to specify the minimum remote assurance 256 * level in the JSON representation of this control. 257 */ 258 @NotNull private static final String JSON_FIELD_MINIMUM_REMOTE_LEVEL = 259 "minimum-remote-level"; 260 261 262 263 /** 264 * The name of the field used to indicate whether to send the operation 265 * response immediately in the JSON representation of this control. 266 */ 267 @NotNull private static final String JSON_FIELD_SEND_RESPONSE_IMMEDIATELY = 268 "send-response-immediately"; 269 270 271 272 /** 273 * The name of the field used to specify the assurance timeout in the JSON 274 * representation of this control. 275 */ 276 @NotNull private static final String JSON_FIELD_TIMEOUT_MILLIS = 277 "timeout-millis"; 278 279 280 281 /** 282 * The serial version UID for this serializable class. 283 */ 284 private static final long serialVersionUID = -2013933506118879241L; 285 286 287 288 // The requested maximum local assurance level. 289 @Nullable private final AssuredReplicationLocalLevel maximumLocalLevel; 290 291 // The requested minimum local assurance level. 292 @Nullable private final AssuredReplicationLocalLevel minimumLocalLevel; 293 294 // The requested maximum remote assurance level. 295 @Nullable private final AssuredReplicationRemoteLevel maximumRemoteLevel; 296 297 // The requested minimum remote assurance level. 298 @Nullable private final AssuredReplicationRemoteLevel minimumRemoteLevel; 299 300 // Indicates whether the server should immediately send the operation response 301 // without waiting for assurance processing. 302 private final boolean sendResponseImmediately; 303 304 // The maximum length of time in milliseconds that the server should wait for 305 // the desired assurance level to be attained. 306 @Nullable private final Long timeoutMillis; 307 308 309 310 /** 311 * Creates a new assured replication request control with the provided 312 * information. It will not be critical. 313 * 314 * @param minimumLocalLevel The minimum replication assurance level desired 315 * for servers in the same location as the server 316 * receiving the change. This may be overridden 317 * by the server if the associated operation 318 * matches an assured replication criteria with a 319 * higher local assurance level. If this is 320 * {@code null}, then the server will determine 321 * minimum local assurance level for the 322 * operation. 323 * @param minimumRemoteLevel The minimum replication assurance level desired 324 * for servers in different locations from the 325 * server receiving the change. This may be 326 * overridden by the server if the associated 327 * operation matches an assured replication 328 * criteria with a higher remote assurance level. 329 * If this is {@code null}, then the server will 330 * determine the remote assurance level for the 331 * operation. 332 * @param timeoutMillis The maximum length of time in milliseconds to 333 * wait for the desired assurance to be satisfied. 334 * If this is {@code null}, then the server will 335 * determine the timeout to use. 336 */ 337 public AssuredReplicationRequestControl( 338 @Nullable final AssuredReplicationLocalLevel minimumLocalLevel, 339 @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel, 340 @Nullable final Long timeoutMillis) 341 { 342 this(false, minimumLocalLevel, null, minimumRemoteLevel, null, 343 timeoutMillis, false); 344 } 345 346 347 348 /** 349 * Creates a new assured replication request control with the provided 350 * information. 351 * 352 * @param isCritical Indicates whether the control should be 353 * marked critical. 354 * @param minimumLocalLevel The minimum replication assurance level 355 * desired for servers in the same location 356 * as the server receiving the change. This 357 * may be overridden by the server if the 358 * associated operation matches an assured 359 * replication criteria with a higher local 360 * assurance level. If this is {@code null}, 361 * then the server will determine the minimum 362 * local assurance level for the operation. 363 * @param maximumLocalLevel The maximum replication assurance level 364 * desired for servers in the same location 365 * as the server receiving the change. This 366 * may override the server configuration if 367 * the operation matches an assured 368 * replication criteria that would have 369 * otherwise used a higher local assurance 370 * level. If this is {@code null}, then the 371 * server will determine the maximum local 372 * assurance level for the operation. 373 * @param minimumRemoteLevel The minimum replication assurance level 374 * desired for servers in different locations 375 * from the server receiving the change. 376 * This may be overridden by the server if 377 * the associated operation matches an 378 * assured replication criteria with a higher 379 * remote assurance level. If this is 380 * {@code null}, then the server will 381 * determine the minimum remote assurance 382 * level for the operation. 383 * @param maximumRemoteLevel The maximum replication assurance level 384 * desired for servers in different locations 385 * from the server receiving the change. 386 * This may override the server configuration 387 * if the operation matches an assured 388 * replication criteria that would have 389 * otherwise used a higher remote assurance 390 * level. If this is {@code null}, then the 391 * server will determine the maximum remote 392 * assurance level for the operation. 393 * @param timeoutMillis The maximum length of time in milliseconds 394 * to wait for the desired assurance to be 395 * satisfied. If this is {@code null}, then 396 * the server will determine the timeout to 397 * use. 398 * @param sendResponseImmediately Indicates whether the server should 399 * send the response to the client immediately after the change 400 * has been applied to the server receiving the change, without 401 * waiting for the desired assurance to be satisfied. 402 */ 403 public AssuredReplicationRequestControl(final boolean isCritical, 404 @Nullable final AssuredReplicationLocalLevel minimumLocalLevel, 405 @Nullable final AssuredReplicationLocalLevel maximumLocalLevel, 406 @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel, 407 @Nullable final AssuredReplicationRemoteLevel maximumRemoteLevel, 408 @Nullable final Long timeoutMillis, 409 final boolean sendResponseImmediately) 410 { 411 super(ASSURED_REPLICATION_REQUEST_OID, isCritical, 412 encodeValue(minimumLocalLevel, maximumLocalLevel, minimumRemoteLevel, 413 maximumRemoteLevel, sendResponseImmediately, timeoutMillis)); 414 415 this.minimumLocalLevel = minimumLocalLevel; 416 this.maximumLocalLevel = maximumLocalLevel; 417 this.minimumRemoteLevel = minimumRemoteLevel; 418 this.maximumRemoteLevel = maximumRemoteLevel; 419 this.sendResponseImmediately = sendResponseImmediately; 420 this.timeoutMillis = timeoutMillis; 421 } 422 423 424 425 /** 426 * Creates a new assured replication request control from the provided generic 427 * control. 428 * 429 * @param c The generic control to decode as an assured replication request 430 * control. It must not be {@code null}. 431 * 432 * @throws LDAPException If the provided generic control cannot be parsed as 433 * an assured replication request control. 434 */ 435 public AssuredReplicationRequestControl(@NotNull final Control c) 436 throws LDAPException 437 { 438 super(c); 439 440 final ASN1OctetString value = c.getValue(); 441 if (value == null) 442 { 443 throw new LDAPException(ResultCode.DECODING_ERROR, 444 ERR_ASSURED_REPLICATION_REQUEST_NO_VALUE.get()); 445 } 446 447 AssuredReplicationLocalLevel maxLocalLevel = null; 448 AssuredReplicationLocalLevel minLocalLevel = null; 449 AssuredReplicationRemoteLevel maxRemoteLevel = null; 450 AssuredReplicationRemoteLevel minRemoteLevel = null; 451 boolean sendImmediately = false; 452 Long timeout = null; 453 454 try 455 { 456 for (final ASN1Element e : 457 ASN1Sequence.decodeAsSequence(value.getValue()).elements()) 458 { 459 switch (e.getType()) 460 { 461 case TYPE_MIN_LOCAL_LEVEL: 462 int intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 463 minLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue); 464 if (minLocalLevel == null) 465 { 466 throw new LDAPException(ResultCode.DECODING_ERROR, 467 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_LOCAL_LEVEL.get( 468 intValue)); 469 } 470 break; 471 472 case TYPE_MAX_LOCAL_LEVEL: 473 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 474 maxLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue); 475 if (maxLocalLevel == null) 476 { 477 throw new LDAPException(ResultCode.DECODING_ERROR, 478 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_LOCAL_LEVEL.get( 479 intValue)); 480 } 481 break; 482 483 case TYPE_MIN_REMOTE_LEVEL: 484 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 485 minRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue); 486 if (minRemoteLevel == null) 487 { 488 throw new LDAPException(ResultCode.DECODING_ERROR, 489 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_REMOTE_LEVEL.get( 490 intValue)); 491 } 492 break; 493 494 case TYPE_MAX_REMOTE_LEVEL: 495 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 496 maxRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue); 497 if (maxRemoteLevel == null) 498 { 499 throw new LDAPException(ResultCode.DECODING_ERROR, 500 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_REMOTE_LEVEL.get( 501 intValue)); 502 } 503 break; 504 505 case TYPE_SEND_RESPONSE_IMMEDIATELY: 506 sendImmediately = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 507 break; 508 509 case TYPE_TIMEOUT: 510 timeout = ASN1Long.decodeAsLong(e).longValue(); 511 break; 512 513 default: 514 throw new LDAPException(ResultCode.DECODING_ERROR, 515 ERR_ASSURED_REPLICATION_REQUEST_UNEXPECTED_ELEMENT_TYPE.get( 516 StaticUtils.toHex(e.getType()))); 517 } 518 } 519 } 520 catch (final LDAPException le) 521 { 522 Debug.debugException(le); 523 throw le; 524 } 525 catch (final Exception e) 526 { 527 Debug.debugException(e); 528 throw new LDAPException(ResultCode.DECODING_ERROR, 529 ERR_ASSURED_REPLICATION_REQUEST_ERROR_DECODING_VALUE.get( 530 StaticUtils.getExceptionMessage(e)), 531 e); 532 } 533 534 minimumLocalLevel = minLocalLevel; 535 maximumLocalLevel = maxLocalLevel; 536 minimumRemoteLevel = minRemoteLevel; 537 maximumRemoteLevel = maxRemoteLevel; 538 sendResponseImmediately = sendImmediately; 539 timeoutMillis = timeout; 540 } 541 542 543 544 /** 545 * Encodes the provided information as needed for use as the value of this 546 * control. 547 * 548 * @param minimumLocalLevel The minimum replication assurance level 549 * desired for servers in the same location 550 * as the server receiving the change. This 551 * may be overridden by the server if the 552 * associated operation matches an assured 553 * replication criteria with a higher local 554 * assurance level. If this is {@code null}, 555 * then the server will determine the minimum 556 * local assurance level for the operation. 557 * @param maximumLocalLevel The maximum replication assurance level 558 * desired for servers in the same location 559 * as the server receiving the change. This 560 * may override the server configuration if 561 * the operation matches an assured 562 * replication criteria that would have 563 * otherwise used a higher local assurance 564 * level. If this is {@code null}, then the 565 * server will determine the maximum local 566 * assurance level for the operation. 567 * @param minimumRemoteLevel The minimum replication assurance level 568 * desired for servers in different locations 569 * from the server receiving the change. 570 * This may be overridden by the server if 571 * the associated operation matches an 572 * assured replication criteria with a higher 573 * remote assurance level. If this is 574 * {@code null}, then the server will 575 * determine the minimum remote assurance 576 * level for the operation. 577 * @param maximumRemoteLevel The maximum replication assurance level 578 * desired for servers in different locations 579 * from the server receiving the change. 580 * This may override the server configuration 581 * if the operation matches an assured 582 * replication criteria that would have 583 * otherwise used a higher remote assurance 584 * level. If this is {@code null}, then the 585 * server will determine the maximum remote 586 * assurance level for the operation. 587 * @param timeoutMillis The maximum length of time in milliseconds 588 * to wait for the desired assurance to be 589 * satisfied. If this is {@code null}, then 590 * the server will determine the timeout to 591 * use. 592 * @param sendResponseImmediately Indicates whether the server should 593 * send the response to the client immediately after the change 594 * has been applied to the server receiving the change, without 595 * waiting for the desired assurance to be satisfied. 596 * 597 * @return The ASN.1 octet string containing the encoded value. 598 */ 599 @NotNull() 600 private static ASN1OctetString encodeValue( 601 @Nullable final AssuredReplicationLocalLevel minimumLocalLevel, 602 @Nullable final AssuredReplicationLocalLevel maximumLocalLevel, 603 @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel, 604 @Nullable final AssuredReplicationRemoteLevel maximumRemoteLevel, 605 final boolean sendResponseImmediately, 606 @Nullable final Long timeoutMillis) 607 { 608 final ArrayList<ASN1Element> elements = new ArrayList<>(6); 609 610 if (minimumLocalLevel != null) 611 { 612 elements.add(new ASN1Enumerated(TYPE_MIN_LOCAL_LEVEL, 613 minimumLocalLevel.intValue())); 614 } 615 616 if (maximumLocalLevel != null) 617 { 618 elements.add(new ASN1Enumerated(TYPE_MAX_LOCAL_LEVEL, 619 maximumLocalLevel.intValue())); 620 } 621 622 if (minimumRemoteLevel != null) 623 { 624 elements.add(new ASN1Enumerated(TYPE_MIN_REMOTE_LEVEL, 625 minimumRemoteLevel.intValue())); 626 } 627 628 if (maximumRemoteLevel != null) 629 { 630 elements.add(new ASN1Enumerated(TYPE_MAX_REMOTE_LEVEL, 631 maximumRemoteLevel.intValue())); 632 } 633 634 if (sendResponseImmediately) 635 { 636 elements.add(new ASN1Boolean(TYPE_SEND_RESPONSE_IMMEDIATELY, true)); 637 } 638 639 if (timeoutMillis != null) 640 { 641 elements.add(new ASN1Long(TYPE_TIMEOUT, timeoutMillis)); 642 } 643 644 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 645 } 646 647 648 649 /** 650 * Retrieves the minimum desired replication level of assurance for local 651 * servers (i.e., servers in the same location as the server that originally 652 * received the change), if defined. This may be overridden by the server if 653 * the associated operation matches an assured replication criteria with a 654 * higher local assurance level. 655 * 656 * @return The minimum desired replication level of assurance for local 657 * servers, or {@code null} if the server should determine the 658 * minimum local assurance level for the operation. 659 */ 660 @Nullable() 661 public AssuredReplicationLocalLevel getMinimumLocalLevel() 662 { 663 return minimumLocalLevel; 664 } 665 666 667 668 /** 669 * Retrieves the maximum desired replication level of assurance for local 670 * servers (i.e., servers in the same location as the server that originally 671 * received the change), if defined. This may override the server 672 * configuration if the operation matches an assured replication criteria that 673 * would have otherwise used a higher local assurance level. 674 * 675 * @return The maximum desired replication level of assurance for local 676 * servers, or {@code null} if the server should determine the 677 * maximum local assurance level for the operation. 678 */ 679 @Nullable() 680 public AssuredReplicationLocalLevel getMaximumLocalLevel() 681 { 682 return maximumLocalLevel; 683 } 684 685 686 687 /** 688 * Retrieves the minimum desired replication level of assurance for remote 689 * servers (i.e., servers in locations different from the server that 690 * originally received the change), if defined. This may be overridden by the 691 * server if the associated operation matches an assured replication 692 * criteria with a higher remote assurance level. 693 * 694 * @return The minimum desired replication level of assurance for remote 695 * servers, or {@code null} if the server should determine the 696 * minimum remote assurance level for the operation. 697 */ 698 @Nullable() 699 public AssuredReplicationRemoteLevel getMinimumRemoteLevel() 700 { 701 return minimumRemoteLevel; 702 } 703 704 705 706 /** 707 * Retrieves the maximum desired replication level of assurance for remote 708 * servers (i.e., servers in locations different from the server that 709 * originally received the change), if defined. This may override the server 710 * configuration if the operation matches an assured replication criteria that 711 * would have otherwise used a higher remote assurance level. 712 * 713 * @return The maximum desired replication level of assurance for remote 714 * servers, or {@code null} if the server should determine the 715 * maximum remote assurance level for the operation. 716 */ 717 @Nullable() 718 public AssuredReplicationRemoteLevel getMaximumRemoteLevel() 719 { 720 return maximumRemoteLevel; 721 } 722 723 724 725 /** 726 * Indicates whether the server that originally received the change should 727 * return the operation result immediately, without waiting for the requested 728 * assurance processing to complete. 729 * 730 * @return {@code false} if the server should wait to return the operation 731 * result until the desired assurance has been attained or a timeout 732 * has occurred, or {@code true} if the server should return the 733 * result immediately. 734 */ 735 public boolean sendResponseImmediately() 736 { 737 return sendResponseImmediately; 738 } 739 740 741 742 /** 743 * Retrieves the maximum length of time in milliseconds that the operation 744 * response should be delayed while waiting for the desired level of 745 * assurance to be attained. 746 * 747 * @return The maximum length of time in milliseconds that the operation 748 * response should be delayed while waiting for the desired level of 749 * assurance to be attained. 750 */ 751 @Nullable() 752 public Long getTimeoutMillis() 753 { 754 return timeoutMillis; 755 } 756 757 758 759 /** 760 * {@inheritDoc} 761 */ 762 @Override() 763 @NotNull() 764 public String getControlName() 765 { 766 return INFO_CONTROL_NAME_ASSURED_REPLICATION_REQUEST.get(); 767 } 768 769 770 771 /** 772 * Retrieves a representation of this assured replication request control as a 773 * JSON object. The JSON object uses the following fields: 774 * <UL> 775 * <LI> 776 * {@code oid} -- A mandatory string field whose value is the object 777 * identifier for this control. For the assured replication request 778 * control, the OID is "1.3.6.1.4.1.30221.2.5.28". 779 * </LI> 780 * <LI> 781 * {@code control-name} -- An optional string field whose value is a 782 * human-readable name for this control. This field is only intended for 783 * descriptive purposes, and when decoding a control, the {@code oid} 784 * field should be used to identify the type of control. 785 * </LI> 786 * <LI> 787 * {@code criticality} -- A mandatory Boolean field used to indicate 788 * whether this control is considered critical. 789 * </LI> 790 * <LI> 791 * {@code value-base64} -- An optional string field whose value is a 792 * base64-encoded representation of the raw value for this assured 793 * replication request control. Exactly one of the {@code value-base64} 794 * and {@code value-json} fields must be present. 795 * </LI> 796 * <LI> 797 * {@code value-json} -- An optional JSON object field whose value is a 798 * user-friendly representation of the value for this assured replication 799 * request control. Exactly one of the {@code value-base64} and 800 * {@code value-json} fields must be present, and if the 801 * {@code value-json} field is used, then it will use the following 802 * fields: 803 * <UL> 804 * <LI> 805 * {@code minimum-local-level} -- An optional string field whose 806 * value is the name of the minimum assurance level desired for 807 * replicas in the same location as the target server. The value may 808 * be one of "{@code none}", "{@code received-any-server}", or 809 * "{@code processed-all-servers}". 810 * </LI> 811 * <LI> 812 * {@code maximum-local-level} -- An optional string field whose 813 * value is the name of the maximum assurance level desired for 814 * replicas in the same location as the target server. The value may 815 * be one of "{@code none}", "{@code received-any-server}", or 816 * "{@code processed-all-servers}". 817 * </LI> 818 * <LI> 819 * {@code minimum-remote-level} -- An optional string field whose 820 * value is the name of the minimum assurance level desired for 821 * replicas in a different location from the target server. The value 822 * may be one of "{@code none}", 823 * "{@code received-any-remote-location}", 824 * "{@code received-all-remote-locations}", or 825 * "{@code processed-all-remote-servers}". 826 * </LI> 827 * <LI> 828 * {@code maximum-remote-level} -- An optional string field whose 829 * value is the name of the maximum assurance level desired for 830 * replicas in a different location from the target server. The value 831 * may be one of "{@code none}", 832 * "{@code received-any-remote-location}", 833 * "{@code received-all-remote-locations}", or 834 * "{@code processed-all-remote-servers}". 835 * </LI> 836 * <LI> 837 * {@code timeout-millis} -- An optional integer field whose value is 838 * the maximum length of time in milliseconds that the server should 839 * wait for assurance to be satisfied. 840 * </LI> 841 * <LI> 842 * {@code send-response-immediately} -- A mandatory Boolean field that 843 * indicates whether the server should return the response to the 844 * client immediately after applying the change locally, even if it 845 * has not yet been replicated. 846 * </LI> 847 * </UL> 848 * </LI> 849 * </UL> 850 * 851 * @return A JSON object that contains a representation of this control. 852 */ 853 @Override() 854 @NotNull() 855 public JSONObject toJSONControl() 856 { 857 final Map<String,JSONValue> jsonValueFields = new LinkedHashMap<>(); 858 859 if (minimumLocalLevel != null) 860 { 861 jsonValueFields.put(JSON_FIELD_MINIMUM_LOCAL_LEVEL, 862 new JSONString(minimumLocalLevel.getName())); 863 } 864 865 if (maximumLocalLevel != null) 866 { 867 jsonValueFields.put(JSON_FIELD_MAXIMUM_LOCAL_LEVEL, 868 new JSONString(maximumLocalLevel.getName())); 869 } 870 871 if (minimumRemoteLevel != null) 872 { 873 jsonValueFields.put(JSON_FIELD_MINIMUM_REMOTE_LEVEL, 874 new JSONString(minimumRemoteLevel.getName())); 875 } 876 877 if (maximumRemoteLevel != null) 878 { 879 jsonValueFields.put(JSON_FIELD_MAXIMUM_REMOTE_LEVEL, 880 new JSONString(maximumRemoteLevel.getName())); 881 } 882 883 if (timeoutMillis != null) 884 { 885 jsonValueFields.put(JSON_FIELD_TIMEOUT_MILLIS, 886 new JSONNumber(timeoutMillis)); 887 } 888 889 jsonValueFields.put(JSON_FIELD_SEND_RESPONSE_IMMEDIATELY, 890 new JSONBoolean(sendResponseImmediately)); 891 892 return new JSONObject( 893 new JSONField(JSONControlDecodeHelper.JSON_FIELD_OID, 894 ASSURED_REPLICATION_REQUEST_OID), 895 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME, 896 INFO_CONTROL_NAME_ASSURED_REPLICATION_REQUEST.get()), 897 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY, 898 isCritical()), 899 new JSONField(JSONControlDecodeHelper.JSON_FIELD_VALUE_JSON, 900 new JSONObject(jsonValueFields))); 901 } 902 903 904 905 /** 906 * Attempts to decode the provided object as a JSON representation of an 907 * assured replication request control. 908 * 909 * @param controlObject The JSON object to be decoded. It must not be 910 * {@code null}. 911 * @param strict Indicates whether to use strict mode when decoding 912 * the provided JSON object. If this is {@code true}, 913 * then this method will throw an exception if the 914 * provided JSON object contains any unrecognized 915 * fields. If this is {@code false}, then unrecognized 916 * fields will be ignored. 917 * 918 * @return The assured replication control that was decoded from the provided 919 * JSON object. 920 * 921 * @throws LDAPException If the provided JSON object cannot be parsed as a 922 * valid assured replication request control. 923 */ 924 @NotNull() 925 public static AssuredReplicationRequestControl decodeJSONControl( 926 @NotNull final JSONObject controlObject, 927 final boolean strict) 928 throws LDAPException 929 { 930 final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper( 931 controlObject, strict, true, true); 932 933 final ASN1OctetString rawValue = jsonControl.getRawValue(); 934 if (rawValue != null) 935 { 936 return new AssuredReplicationRequestControl(new Control( 937 jsonControl.getOID(), jsonControl.getCriticality(), rawValue)); 938 } 939 940 941 AssuredReplicationLocalLevel minimumLocalLevel = null; 942 AssuredReplicationLocalLevel maximumLocalLevel = null; 943 AssuredReplicationRemoteLevel minimumRemoteLevel = null; 944 AssuredReplicationRemoteLevel maximumRemoteLevel = null; 945 Long timeoutMillis = null; 946 Boolean sendImmediately = null; 947 final JSONObject valueObject = jsonControl.getValueObject(); 948 949 final String minLocalLevelStr = 950 valueObject.getFieldAsString(JSON_FIELD_MINIMUM_LOCAL_LEVEL); 951 if (minLocalLevelStr != null) 952 { 953 minimumLocalLevel = 954 AssuredReplicationLocalLevel.forName(minLocalLevelStr); 955 if (minimumLocalLevel == null) 956 { 957 throw new LDAPException(ResultCode.DECODING_ERROR, 958 ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MIN_LOCAL_LEVEL.get( 959 controlObject.toSingleLineString(), 960 minLocalLevelStr)); 961 } 962 } 963 964 final String maxLocalLevelStr = 965 valueObject.getFieldAsString(JSON_FIELD_MAXIMUM_LOCAL_LEVEL); 966 if (maxLocalLevelStr != null) 967 { 968 maximumLocalLevel = 969 AssuredReplicationLocalLevel.forName(maxLocalLevelStr); 970 if (maximumLocalLevel == null) 971 { 972 throw new LDAPException(ResultCode.DECODING_ERROR, 973 ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MAX_LOCAL_LEVEL.get( 974 controlObject.toSingleLineString(), 975 maxLocalLevelStr)); 976 } 977 } 978 979 final String minRemoteLevelStr = 980 valueObject.getFieldAsString(JSON_FIELD_MINIMUM_REMOTE_LEVEL); 981 if (minRemoteLevelStr != null) 982 { 983 minimumRemoteLevel = 984 AssuredReplicationRemoteLevel.forName(minRemoteLevelStr); 985 if (minimumRemoteLevel == null) 986 { 987 throw new LDAPException(ResultCode.DECODING_ERROR, 988 ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MIN_REMOTE_LEVEL.get( 989 controlObject.toSingleLineString(), 990 minRemoteLevelStr)); 991 } 992 } 993 994 final String maxRemoteLevelStr = 995 valueObject.getFieldAsString(JSON_FIELD_MAXIMUM_REMOTE_LEVEL); 996 if (maxRemoteLevelStr != null) 997 { 998 maximumRemoteLevel = 999 AssuredReplicationRemoteLevel.forName(maxRemoteLevelStr); 1000 if (maximumRemoteLevel == null) 1001 { 1002 throw new LDAPException(ResultCode.DECODING_ERROR, 1003 ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MAX_REMOTE_LEVEL.get( 1004 controlObject.toSingleLineString(), 1005 maxRemoteLevelStr)); 1006 } 1007 } 1008 1009 timeoutMillis = valueObject.getFieldAsLong(JSON_FIELD_TIMEOUT_MILLIS); 1010 1011 sendImmediately = 1012 valueObject.getFieldAsBoolean(JSON_FIELD_SEND_RESPONSE_IMMEDIATELY); 1013 if (sendImmediately == null) 1014 { 1015 throw new LDAPException(ResultCode.DECODING_ERROR, 1016 ERR_ASSURED_REPLICATION_REQUEST_JSON_MISSING_FIELD.get( 1017 controlObject.toSingleLineString(), 1018 JSON_FIELD_SEND_RESPONSE_IMMEDIATELY)); 1019 } 1020 1021 1022 if (strict) 1023 { 1024 final List<String> unrecognizedFields = 1025 JSONControlDecodeHelper.getControlObjectUnexpectedFields( 1026 valueObject, JSON_FIELD_MINIMUM_LOCAL_LEVEL, 1027 JSON_FIELD_MAXIMUM_LOCAL_LEVEL, JSON_FIELD_MINIMUM_REMOTE_LEVEL, 1028 JSON_FIELD_MAXIMUM_REMOTE_LEVEL, JSON_FIELD_TIMEOUT_MILLIS, 1029 JSON_FIELD_SEND_RESPONSE_IMMEDIATELY); 1030 if (! unrecognizedFields.isEmpty()) 1031 { 1032 throw new LDAPException(ResultCode.DECODING_ERROR, 1033 ERR_ASSURED_REPLICATION_REQUEST_JSON_CONTROL_UNRECOGNIZED_FIELD 1034 .get(controlObject.toSingleLineString(), 1035 unrecognizedFields.get(0))); 1036 } 1037 } 1038 1039 1040 return new AssuredReplicationRequestControl(jsonControl.getCriticality(), 1041 minimumLocalLevel, maximumLocalLevel, minimumRemoteLevel, 1042 maximumRemoteLevel, timeoutMillis, sendImmediately); 1043 } 1044 1045 1046 1047 /** 1048 * {@inheritDoc} 1049 */ 1050 @Override() 1051 public void toString(@NotNull final StringBuilder buffer) 1052 { 1053 buffer.append("AssuredReplicationRequestControl(isCritical="); 1054 buffer.append(isCritical()); 1055 1056 if (minimumLocalLevel != null) 1057 { 1058 buffer.append(", minimumLocalLevel="); 1059 buffer.append(minimumLocalLevel.name()); 1060 } 1061 1062 if (maximumLocalLevel != null) 1063 { 1064 buffer.append(", maximumLocalLevel="); 1065 buffer.append(maximumLocalLevel.name()); 1066 } 1067 1068 if (minimumRemoteLevel != null) 1069 { 1070 buffer.append(", minimumRemoteLevel="); 1071 buffer.append(minimumRemoteLevel.name()); 1072 } 1073 1074 if (maximumRemoteLevel != null) 1075 { 1076 buffer.append(", maximumRemoteLevel="); 1077 buffer.append(maximumRemoteLevel.name()); 1078 } 1079 1080 buffer.append(", sendResponseImmediately="); 1081 buffer.append(sendResponseImmediately); 1082 1083 if (timeoutMillis != null) 1084 { 1085 buffer.append(", timeoutMillis="); 1086 buffer.append(timeoutMillis); 1087 } 1088 1089 buffer.append(')'); 1090 } 1091}