001/* 002 * Copyright 2013-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.controls; 022 023 024 025import java.util.ArrayList; 026 027import com.unboundid.asn1.ASN1Boolean; 028import com.unboundid.asn1.ASN1Element; 029import com.unboundid.asn1.ASN1Enumerated; 030import com.unboundid.asn1.ASN1Long; 031import com.unboundid.asn1.ASN1OctetString; 032import com.unboundid.asn1.ASN1Sequence; 033import com.unboundid.ldap.sdk.Control; 034import com.unboundid.ldap.sdk.LDAPException; 035import com.unboundid.ldap.sdk.ResultCode; 036import com.unboundid.util.Debug; 037import com.unboundid.util.NotMutable; 038import com.unboundid.util.StaticUtils; 039import com.unboundid.util.ThreadSafety; 040import com.unboundid.util.ThreadSafetyLevel; 041 042import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 043 044 045 046/** 047 * This class provides an implementation of an LDAP control that can be included 048 * in add, bind, modify, modify DN, and certain extended requests to indicate 049 * the level of replication assurance desired for the associated operation. 050 * <BR> 051 * <BLOCKQUOTE> 052 * <B>NOTE:</B> This class, and other classes within the 053 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 054 * supported for use against Ping Identity, UnboundID, and 055 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 056 * for proprietary functionality or for external specifications that are not 057 * considered stable or mature enough to be guaranteed to work in an 058 * interoperable way with other types of LDAP servers. 059 * </BLOCKQUOTE> 060 * <BR> 061 * The OID for this control is 1.3.6.1.4.1.30221.2.5.28, and it may have a 062 * criticality of either TRUE or FALSE. It must have a value with the following 063 * encoding: 064 * <PRE> 065 * AssuredReplicationRequest ::= SEQUENCE { 066 * minimumLocalLevel [0] LocalLevel OPTIONAL, 067 * maximumLocalLevel [1] LocalLevel OPTIONAL, 068 * minimumRemoteLevel [2] RemoteLevel OPTIONAL, 069 * maximumRemoteLevel [3] RemoteLevel OPTIONAL, 070 * timeoutMillis [4] INTEGER (1 .. 2147483647) OPTIONAL, 071 * sendResponseImmediately [5] BOOLEAN DEFAULT FALSE, 072 * ... } 073 * 074 * LocalLevel ::= ENUMERATED { 075 * none (0), 076 * receivedAnyServer (1), 077 * processedAllServers (2), 078 * ... } 079 * 080 * RemoteLevel ::= ENUMERATED { 081 * none (0), 082 * receivedAnyRemoteLocation (1), 083 * receivedAllRemoteLocations (2), 084 * processedAllRemoteServers (3), 085 * ... } 086 * </PRE> 087 * <BR><BR> 088 * <H2>Example</H2> 089 * The following example demonstrates the use of the assured replication request 090 * control in conjunction with a delete operation to request that the server not 091 * return the delete result to the client until the delete has been applied to 092 * all available servers in the local data center and has also been replicated 093 * to at least one remote data center: 094 * <PRE> 095 * DeleteRequest deleteRequest = new DeleteRequest( 096 * "uid=test.user,ou=People,dc=example,dc=com"); 097 * deleteRequest.addControl(new AssuredReplicationRequestControl( 098 * AssuredReplicationLocalLevel.PROCESSED_ALL_SERVERS, 099 * AssuredReplicationRemoteLevel.RECEIVED_ANY_REMOTE_LOCATION, 100 * 5000L)); 101 * LDAPResult deleteResult = connection.delete(deleteRequest); 102 * 103 * if (deleteResult.getResultCode() == ResultCode.SUCCESS) 104 * { 105 * AssuredReplicationResponseControl assuredReplicationResponse = 106 * AssuredReplicationResponseControl.get(deleteResult); 107 * if (assuredReplicationResponse == null) 108 * { 109 * // The entry was deleted, but its replication could not be confirmed in 110 * // either the local or remote data centers. 111 * } 112 * else 113 * { 114 * if (assuredReplicationResponse.localAssuranceSatisfied()) 115 * { 116 * if (assuredReplicationResponse.remoteAssuranceSatisfied()) 117 * { 118 * // The entry was deleted. The delete has been applied across all 119 * // available local servers, and has been replicated to at least one 120 * // remote data center. 121 * } 122 * else 123 * { 124 * // The entry was deleted. The delete has been applied across all 125 * // available local servers, but cannot be confirmed to have yet 126 * // been replicated to any remote data centers. 127 * } 128 * } 129 * else if (assuredReplicationResponse.remoteAssuranceSatisfied()) 130 * { 131 * // The entry was deleted. The delete has been confirmed to have been 132 * // replicated to at least one remote data center, but cannot be 133 * // confirmed to have yet been applied to all available local servers. 134 * } 135 * else 136 * { 137 * // The entry was deleted, but its replication could not be confirmed 138 * // to either local servers or remote data centers. 139 * } 140 * } 141 * } 142 * else 143 * { 144 * // The entry could not be deleted. 145 * } 146 * </PRE> 147 * 148 * @see AssuredReplicationResponseControl 149 */ 150@NotMutable() 151@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 152public final class AssuredReplicationRequestControl 153 extends Control 154{ 155 /** 156 * The OID (1.3.6.1.4.1.30221.2.5.28) for the assured replication request 157 * control. 158 */ 159 public static final String ASSURED_REPLICATION_REQUEST_OID = 160 "1.3.6.1.4.1.30221.2.5.28"; 161 162 163 /** 164 * The BER type for the minimum local assurance level. 165 */ 166 private static final byte TYPE_MIN_LOCAL_LEVEL = (byte) 0x80; 167 168 169 /** 170 * The BER type for the maximum local assurance level. 171 */ 172 private static final byte TYPE_MAX_LOCAL_LEVEL = (byte) 0x81; 173 174 175 /** 176 * The BER type for the minimum remote assurance level. 177 */ 178 private static final byte TYPE_MIN_REMOTE_LEVEL = (byte) 0x82; 179 180 181 /** 182 * The BER type for the maximum remote assurance level. 183 */ 184 private static final byte TYPE_MAX_REMOTE_LEVEL = (byte) 0x83; 185 186 187 /** 188 * The BER type for the maximum remote assurance level. 189 */ 190 private static final byte TYPE_SEND_RESPONSE_IMMEDIATELY = (byte) 0x84; 191 192 193 /** 194 * The BER type for the timeout. 195 */ 196 private static final byte TYPE_TIMEOUT = (byte) 0x85; 197 198 199 200 /** 201 * The serial version UID for this serializable class. 202 */ 203 private static final long serialVersionUID = -2013933506118879241L; 204 205 206 207 // The requested maximum local assurance level. 208 private final AssuredReplicationLocalLevel maximumLocalLevel; 209 210 // The requested minimum local assurance level. 211 private final AssuredReplicationLocalLevel minimumLocalLevel; 212 213 // The requested maximum remote assurance level. 214 private final AssuredReplicationRemoteLevel maximumRemoteLevel; 215 216 // The requested minimum remote assurance level. 217 private final AssuredReplicationRemoteLevel minimumRemoteLevel; 218 219 // Indicates whether the server should immediately send the operation response 220 // without waiting for assurance processing. 221 private final boolean sendResponseImmediately; 222 223 // The maximum length of time in milliseconds that the server should wait for 224 // the desired assurance level to be attained. 225 private final Long timeoutMillis; 226 227 228 229 /** 230 * Creates a new assured replication request control with the provided 231 * information. It will not be critical. 232 * 233 * @param minimumLocalLevel The minimum replication assurance level desired 234 * for servers in the same location as the server 235 * receiving the change. This may be overridden 236 * by the server if the associated operation 237 * matches an assured replication criteria with a 238 * higher local assurance level. If this is 239 * {@code null}, then the server will determine 240 * minimum local assurance level for the 241 * operation. 242 * @param minimumRemoteLevel The minimum replication assurance level desired 243 * for servers in different locations from the 244 * server receiving the change. This may be 245 * overridden by the server if the associated 246 * operation matches an assured replication 247 * criteria with a higher remote assurance level. 248 * If this is {@code null}, then the server will 249 * determine the remote assurance level for the 250 * operation. 251 * @param timeoutMillis The maximum length of time in milliseconds to 252 * wait for the desired assurance to be satisfied. 253 * If this is {@code null}, then the server will 254 * determine the timeout to use. 255 */ 256 public AssuredReplicationRequestControl( 257 final AssuredReplicationLocalLevel minimumLocalLevel, 258 final AssuredReplicationRemoteLevel minimumRemoteLevel, 259 final Long timeoutMillis) 260 { 261 this(false, minimumLocalLevel, null, minimumRemoteLevel, null, 262 timeoutMillis, false); 263 } 264 265 266 267 /** 268 * Creates a new assured replication request control with the provided 269 * information. 270 * 271 * @param isCritical Indicates whether the control should be 272 * marked critical. 273 * @param minimumLocalLevel The minimum replication assurance level 274 * desired for servers in the same location 275 * as the server receiving the change. This 276 * may be overridden by the server if the 277 * associated operation matches an assured 278 * replication criteria with a higher local 279 * assurance level. If this is {@code null}, 280 * then the server will determine the minimum 281 * local assurance level for the operation. 282 * @param maximumLocalLevel The maximum replication assurance level 283 * desired for servers in the same location 284 * as the server receiving the change. This 285 * may override the server configuration if 286 * the operation matches an assured 287 * replication criteria that would have 288 * otherwise used a higher local assurance 289 * level. If this is {@code null}, then the 290 * server will determine the maximum local 291 * assurance level for the operation. 292 * @param minimumRemoteLevel The minimum replication assurance level 293 * desired for servers in different locations 294 * from the server receiving the change. 295 * This may be overridden by the server if 296 * the associated operation matches an 297 * assured replication criteria with a higher 298 * remote assurance level. If this is 299 * {@code null}, then the server will 300 * determine the minimum remote assurance 301 * level for the operation. 302 * @param maximumRemoteLevel The maximum replication assurance level 303 * desired for servers in different locations 304 * from the server receiving the change. 305 * This may override the server configuration 306 * if the operation matches an assured 307 * replication criteria that would have 308 * otherwise used a higher remote assurance 309 * level. If this is {@code null}, then the 310 * server will determine the maximum remote 311 * assurance level for the operation. 312 * @param timeoutMillis The maximum length of time in milliseconds 313 * to wait for the desired assurance to be 314 * satisfied. If this is {@code null}, then 315 * the server will determine the timeout to 316 * use. 317 * @param sendResponseImmediately Indicates whether the server should 318 * send the response to the client immediately after the change 319 * has been applied to the server receiving the change, without 320 * waiting for the desired assurance to be satisfied. 321 */ 322 public AssuredReplicationRequestControl(final boolean isCritical, 323 final AssuredReplicationLocalLevel minimumLocalLevel, 324 final AssuredReplicationLocalLevel maximumLocalLevel, 325 final AssuredReplicationRemoteLevel minimumRemoteLevel, 326 final AssuredReplicationRemoteLevel maximumRemoteLevel, 327 final Long timeoutMillis, final boolean sendResponseImmediately) 328 { 329 super(ASSURED_REPLICATION_REQUEST_OID, isCritical, 330 encodeValue(minimumLocalLevel, maximumLocalLevel, minimumRemoteLevel, 331 maximumRemoteLevel, sendResponseImmediately, timeoutMillis)); 332 333 this.minimumLocalLevel = minimumLocalLevel; 334 this.maximumLocalLevel = maximumLocalLevel; 335 this.minimumRemoteLevel = minimumRemoteLevel; 336 this.maximumRemoteLevel = maximumRemoteLevel; 337 this.sendResponseImmediately = sendResponseImmediately; 338 this.timeoutMillis = timeoutMillis; 339 } 340 341 342 343 /** 344 * Creates a new assured replication request control from the provided generic 345 * control. 346 * 347 * @param c The generic control to decode as an assured replication request 348 * control. It must not be {@code null}. 349 * 350 * @throws LDAPException If the provided generic control cannot be parsed as 351 * an assured replication request control. 352 */ 353 public AssuredReplicationRequestControl(final Control c) 354 throws LDAPException 355 { 356 super(c); 357 358 final ASN1OctetString value = c.getValue(); 359 if (value == null) 360 { 361 throw new LDAPException(ResultCode.DECODING_ERROR, 362 ERR_ASSURED_REPLICATION_REQUEST_NO_VALUE.get()); 363 } 364 365 AssuredReplicationLocalLevel maxLocalLevel = null; 366 AssuredReplicationLocalLevel minLocalLevel = null; 367 AssuredReplicationRemoteLevel maxRemoteLevel = null; 368 AssuredReplicationRemoteLevel minRemoteLevel = null; 369 boolean sendImmediately = false; 370 Long timeout = null; 371 372 try 373 { 374 for (final ASN1Element e : 375 ASN1Sequence.decodeAsSequence(value.getValue()).elements()) 376 { 377 switch (e.getType()) 378 { 379 case TYPE_MIN_LOCAL_LEVEL: 380 int intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 381 minLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue); 382 if (minLocalLevel == null) 383 { 384 throw new LDAPException(ResultCode.DECODING_ERROR, 385 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_LOCAL_LEVEL.get( 386 intValue)); 387 } 388 break; 389 390 case TYPE_MAX_LOCAL_LEVEL: 391 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 392 maxLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue); 393 if (maxLocalLevel == null) 394 { 395 throw new LDAPException(ResultCode.DECODING_ERROR, 396 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_LOCAL_LEVEL.get( 397 intValue)); 398 } 399 break; 400 401 case TYPE_MIN_REMOTE_LEVEL: 402 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 403 minRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue); 404 if (minRemoteLevel == null) 405 { 406 throw new LDAPException(ResultCode.DECODING_ERROR, 407 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_REMOTE_LEVEL.get( 408 intValue)); 409 } 410 break; 411 412 case TYPE_MAX_REMOTE_LEVEL: 413 intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 414 maxRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue); 415 if (maxRemoteLevel == null) 416 { 417 throw new LDAPException(ResultCode.DECODING_ERROR, 418 ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_REMOTE_LEVEL.get( 419 intValue)); 420 } 421 break; 422 423 case TYPE_SEND_RESPONSE_IMMEDIATELY: 424 sendImmediately = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 425 break; 426 427 case TYPE_TIMEOUT: 428 timeout = ASN1Long.decodeAsLong(e).longValue(); 429 break; 430 431 default: 432 throw new LDAPException(ResultCode.DECODING_ERROR, 433 ERR_ASSURED_REPLICATION_REQUEST_UNEXPECTED_ELEMENT_TYPE.get( 434 StaticUtils.toHex(e.getType()))); 435 } 436 } 437 } 438 catch (final LDAPException le) 439 { 440 Debug.debugException(le); 441 throw le; 442 } 443 catch (final Exception e) 444 { 445 Debug.debugException(e); 446 throw new LDAPException(ResultCode.DECODING_ERROR, 447 ERR_ASSURED_REPLICATION_REQUEST_ERROR_DECODING_VALUE.get( 448 StaticUtils.getExceptionMessage(e)), 449 e); 450 } 451 452 minimumLocalLevel = minLocalLevel; 453 maximumLocalLevel = maxLocalLevel; 454 minimumRemoteLevel = minRemoteLevel; 455 maximumRemoteLevel = maxRemoteLevel; 456 sendResponseImmediately = sendImmediately; 457 timeoutMillis = timeout; 458 } 459 460 461 462 /** 463 * Encodes the provided information as needed for use as the value of this 464 * control. 465 * 466 * @param minimumLocalLevel The minimum replication assurance level 467 * desired for servers in the same location 468 * as the server receiving the change. This 469 * may be overridden by the server if the 470 * associated operation matches an assured 471 * replication criteria with a higher local 472 * assurance level. If this is {@code null}, 473 * then the server will determine the minimum 474 * local assurance level for the operation. 475 * @param maximumLocalLevel The maximum replication assurance level 476 * desired for servers in the same location 477 * as the server receiving the change. This 478 * may override the server configuration if 479 * the operation matches an assured 480 * replication criteria that would have 481 * otherwise used a higher local assurance 482 * level. If this is {@code null}, then the 483 * server will determine the maximum local 484 * assurance level for the operation. 485 * @param minimumRemoteLevel The minimum replication assurance level 486 * desired for servers in different locations 487 * from the server receiving the change. 488 * This may be overridden by the server if 489 * the associated operation matches an 490 * assured replication criteria with a higher 491 * remote assurance level. If this is 492 * {@code null}, then the server will 493 * determine the minimum remote assurance 494 * level for the operation. 495 * @param maximumRemoteLevel The maximum replication assurance level 496 * desired for servers in different locations 497 * from the server receiving the change. 498 * This may override the server configuration 499 * if the operation matches an assured 500 * replication criteria that would have 501 * otherwise used a higher remote assurance 502 * level. If this is {@code null}, then the 503 * server will determine the maximum remote 504 * assurance level for the operation. 505 * @param timeoutMillis The maximum length of time in milliseconds 506 * to wait for the desired assurance to be 507 * satisfied. If this is {@code null}, then 508 * the server will determine the timeout to 509 * use. 510 * @param sendResponseImmediately Indicates whether the server should 511 * send the response to the client immediately after the change 512 * has been applied to the server receiving the change, without 513 * waiting for the desired assurance to be satisfied. 514 * 515 * @return The ASN.1 octet string containing the encoded value. 516 */ 517 private static ASN1OctetString encodeValue( 518 final AssuredReplicationLocalLevel minimumLocalLevel, 519 final AssuredReplicationLocalLevel maximumLocalLevel, 520 final AssuredReplicationRemoteLevel minimumRemoteLevel, 521 final AssuredReplicationRemoteLevel maximumRemoteLevel, 522 final boolean sendResponseImmediately, 523 final Long timeoutMillis) 524 { 525 final ArrayList<ASN1Element> elements = new ArrayList<>(6); 526 527 if (minimumLocalLevel != null) 528 { 529 elements.add(new ASN1Enumerated(TYPE_MIN_LOCAL_LEVEL, 530 minimumLocalLevel.intValue())); 531 } 532 533 if (maximumLocalLevel != null) 534 { 535 elements.add(new ASN1Enumerated(TYPE_MAX_LOCAL_LEVEL, 536 maximumLocalLevel.intValue())); 537 } 538 539 if (minimumRemoteLevel != null) 540 { 541 elements.add(new ASN1Enumerated(TYPE_MIN_REMOTE_LEVEL, 542 minimumRemoteLevel.intValue())); 543 } 544 545 if (maximumRemoteLevel != null) 546 { 547 elements.add(new ASN1Enumerated(TYPE_MAX_REMOTE_LEVEL, 548 maximumRemoteLevel.intValue())); 549 } 550 551 if (sendResponseImmediately) 552 { 553 elements.add(new ASN1Boolean(TYPE_SEND_RESPONSE_IMMEDIATELY, true)); 554 } 555 556 if (timeoutMillis != null) 557 { 558 elements.add(new ASN1Long(TYPE_TIMEOUT, timeoutMillis)); 559 } 560 561 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 562 } 563 564 565 566 /** 567 * Retrieves the minimum desired replication level of assurance for local 568 * servers (i.e., servers in the same location as the server that originally 569 * received the change), if defined. This may be overridden by the server if 570 * the associated operation matches an assured replication criteria with a 571 * higher local assurance level. 572 * 573 * @return The minimum desired replication level of assurance for local 574 * servers, or {@code null} if the server should determine the 575 * minimum local assurance level for the operation. 576 */ 577 public AssuredReplicationLocalLevel getMinimumLocalLevel() 578 { 579 return minimumLocalLevel; 580 } 581 582 583 584 /** 585 * Retrieves the maximum desired replication level of assurance for local 586 * servers (i.e., servers in the same location as the server that originally 587 * received the change), if defined. This may override the server 588 * configuration if the operation matches an assured replication criteria that 589 * would have otherwise used a higher local assurance level. 590 * 591 * @return The maximum desired replication level of assurance for local 592 * servers, or {@code null} if the server should determine the 593 * maximum local assurance level for the operation. 594 */ 595 public AssuredReplicationLocalLevel getMaximumLocalLevel() 596 { 597 return maximumLocalLevel; 598 } 599 600 601 602 /** 603 * Retrieves the minimum desired replication level of assurance for remote 604 * servers (i.e., servers in locations different from the server that 605 * originally received the change), if defined. This may be overridden by the 606 * server if the associated operation matches an assured replication 607 * criteria with a higher remote assurance level. 608 * 609 * @return The minimum desired replication level of assurance for remote 610 * servers, or {@code null} if the server should determine the 611 * minimum remote assurance level for the operation. 612 */ 613 public AssuredReplicationRemoteLevel getMinimumRemoteLevel() 614 { 615 return minimumRemoteLevel; 616 } 617 618 619 620 /** 621 * Retrieves the maximum desired replication level of assurance for remote 622 * servers (i.e., servers in locations different from the server that 623 * originally received the change), if defined. This may override the server 624 * configuration if the operation matches an assured replication criteria that 625 * would have otherwise used a higher remote assurance level. 626 * 627 * @return The maximum desired replication level of assurance for remote 628 * servers, or {@code null} if the server should determine the 629 * maximum remote assurance level for the operation. 630 */ 631 public AssuredReplicationRemoteLevel getMaximumRemoteLevel() 632 { 633 return maximumRemoteLevel; 634 } 635 636 637 638 /** 639 * Indicates whether the server that originally received the change should 640 * return the operation result immediately, without waiting for the requested 641 * assurance processing to complete. 642 * 643 * @return {@code false} if the server should wait to return the operation 644 * result until the desired assurance has been attained or a timeout 645 * has occurred, or {@code true} if the server should return the 646 * result immediately. 647 */ 648 public boolean sendResponseImmediately() 649 { 650 return sendResponseImmediately; 651 } 652 653 654 655 /** 656 * Retrieves the maximum length of time in milliseconds that the operation 657 * response should be delayed while waiting for the desired level of 658 * assurance to be attained. 659 * 660 * @return The maximum length of time in milliseconds that the operation 661 * response should be delayed while waiting for the desired level of 662 * assurance to be attained. 663 */ 664 public Long getTimeoutMillis() 665 { 666 return timeoutMillis; 667 } 668 669 670 671 /** 672 * {@inheritDoc} 673 */ 674 @Override() 675 public String getControlName() 676 { 677 return INFO_CONTROL_NAME_ASSURED_REPLICATION_REQUEST.get(); 678 } 679 680 681 682 /** 683 * {@inheritDoc} 684 */ 685 @Override() 686 public void toString(final StringBuilder buffer) 687 { 688 buffer.append("AssuredReplicationRequestControl(isCritical="); 689 buffer.append(isCritical()); 690 691 if (minimumLocalLevel != null) 692 { 693 buffer.append(", minimumLocalLevel="); 694 buffer.append(minimumLocalLevel.name()); 695 } 696 697 if (maximumLocalLevel != null) 698 { 699 buffer.append(", maximumLocalLevel="); 700 buffer.append(maximumLocalLevel.name()); 701 } 702 703 if (minimumRemoteLevel != null) 704 { 705 buffer.append(", minimumRemoteLevel="); 706 buffer.append(minimumRemoteLevel.name()); 707 } 708 709 if (maximumRemoteLevel != null) 710 { 711 buffer.append(", maximumRemoteLevel="); 712 buffer.append(maximumRemoteLevel.name()); 713 } 714 715 buffer.append(", sendResponseImmediately="); 716 buffer.append(sendResponseImmediately); 717 718 if (timeoutMillis != null) 719 { 720 buffer.append(", timeoutMillis="); 721 buffer.append(timeoutMillis); 722 } 723 724 buffer.append(')'); 725 } 726}