001/* 002 * Copyright 2008-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2008-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) 2008-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.ASN1OctetString; 048import com.unboundid.asn1.ASN1Sequence; 049import com.unboundid.ldap.sdk.Control; 050import com.unboundid.ldap.sdk.JSONControlDecodeHelper; 051import com.unboundid.ldap.sdk.LDAPException; 052import com.unboundid.ldap.sdk.ResultCode; 053import com.unboundid.util.Debug; 054import com.unboundid.util.NotMutable; 055import com.unboundid.util.NotNull; 056import com.unboundid.util.StaticUtils; 057import com.unboundid.util.ThreadSafety; 058import com.unboundid.util.ThreadSafetyLevel; 059import com.unboundid.util.Validator; 060import com.unboundid.util.json.JSONBoolean; 061import com.unboundid.util.json.JSONField; 062import com.unboundid.util.json.JSONObject; 063import com.unboundid.util.json.JSONString; 064import com.unboundid.util.json.JSONValue; 065 066import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 067 068 069 070/** 071 * This class provides a request control which may be used to request that the 072 * associated request be routed to a specific server. It is primarily intended 073 * for use when the request will pass through a Directory Proxy Server to 074 * indicate that which backend server should be used to process the request. 075 * The server ID for the server to use may be obtained using the 076 * {@link GetServerIDRequestControl}. 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 * If the request is processed successfully, then the result should include a 089 * {@link GetServerIDResponseControl} with the server ID of the server that was 090 * used to process the request. It may or may not be the same as the server ID 091 * included in the request control, depending on whether an alternate server was 092 * determined to be better suited to handle the request. 093 * <BR><BR> 094 * The criticality for this control may be either {@code true} or {@code false}. 095 * It must have a value with the following encoding: 096 * <PRE> 097 * RouteToServerRequest ::= SEQUENCE { 098 * serverID [0] OCTET STRING, 099 * allowAlternateServer [1] BOOLEAN, 100 * preferLocalServer [2] BOOLEAN DEFAULT TRUE, 101 * preferNonDegradedServer [3] BOOLEAN DEFAULT TRUE, 102 * ... } 103 * </PRE> 104 * <BR><BR> 105 * <H2>Example</H2> 106 * The following example demonstrates the process of performing a search to 107 * retrieve an entry using the get server ID request control and then sending a 108 * modify request to that same server using the route to server request control. 109 * <PRE> 110 * // Perform a search to find an entry, and use the get server ID request 111 * // control to figure out which server actually processed the request. 112 * SearchRequest searchRequest = new SearchRequest("dc=example,dc=com", 113 * SearchScope.BASE, Filter.createPresenceFilter("objectClass"), 114 * "description"); 115 * searchRequest.addControl(new GetServerIDRequestControl()); 116 * 117 * SearchResultEntry entry = connection.searchForEntry(searchRequest); 118 * GetServerIDResponseControl serverIDControl = 119 * GetServerIDResponseControl.get(entry); 120 * String serverID = serverIDControl.getServerID(); 121 * 122 * // Send a modify request to update the target entry, and include the route 123 * // to server request control to request that the change be processed on the 124 * // same server that processed the request. 125 * ModifyRequest modifyRequest = new ModifyRequest("dc=example,dc=com", 126 * new Modification(ModificationType.REPLACE, "description", 127 * "new description value")); 128 * modifyRequest.addControl(new RouteToServerRequestControl(false, serverID, 129 * true, true, true)); 130 * LDAPResult modifyResult = connection.modify(modifyRequest); 131 * </PRE> 132 */ 133@NotMutable() 134@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 135public final class RouteToServerRequestControl 136 extends Control 137{ 138 /** 139 * The OID (1.3.6.1.4.1.30221.2.5.16) for the route to server request control. 140 */ 141 @NotNull public static final String ROUTE_TO_SERVER_REQUEST_OID = 142 "1.3.6.1.4.1.30221.2.5.16"; 143 144 145 146 /** 147 * The BER type for the server ID element. 148 */ 149 private static final byte TYPE_SERVER_ID = (byte) 0x80; 150 151 152 153 /** 154 * The BER type for the allow alternate server element. 155 */ 156 private static final byte TYPE_ALLOW_ALTERNATE_SERVER = (byte) 0x81; 157 158 159 160 /** 161 * The BER type for the prefer local server element. 162 */ 163 private static final byte TYPE_PREFER_LOCAL_SERVER = (byte) 0x82; 164 165 166 167 /** 168 * The BER type for the prefer non-degraded server element. 169 */ 170 private static final byte TYPE_PREFER_NON_DEGRADED_SERVER = (byte) 0x83; 171 172 173 174 /** 175 * The name of the field used to hold the allow-alternate-server flag in the 176 * JSON representation of this control. 177 */ 178 @NotNull private static final String JSON_FIELD_ALLOW_ALTERNATE_SERVER = 179 "allow-alternate-server"; 180 181 182 183 /** 184 * The name of the field used to hold the prefer-local-server flag in the 185 * JSON representation of this control. 186 */ 187 @NotNull private static final String JSON_FIELD_PREFER_LOCAL_SERVER = 188 "prefer-local-server"; 189 190 191 192 /** 193 * The name of the field used to hold the prefer-non-degraded-server flag in 194 * the JSON representation of this control. 195 */ 196 @NotNull private static final String JSON_FIELD_PREFER_NON_DEGRADED_SERVER = 197 "prefer-non-degraded-server"; 198 199 200 201 /** 202 * The name of the field used to hold the server ID in the JSON 203 * representation of this control. 204 */ 205 @NotNull private static final String JSON_FIELD_SERVER_ID = "server-id"; 206 207 208 209 /** 210 * The serial version UID for this serializable class. 211 */ 212 private static final long serialVersionUID = 2100638364623466061L; 213 214 215 216 // Indicates whether the associated request may be processed by an alternate 217 // server if the server specified by the given server ID is not suitable for 218 // use. 219 private final boolean allowAlternateServer; 220 221 // Indicates whether the associated request should may be routed to an 222 // alternate server if the target server is more remote than an alternate 223 // server. 224 private final boolean preferLocalServer; 225 226 // Indicates whether the associated request should be routed to an alternate 227 // server if the target server is in a degraded state and an alternate server 228 // is not in a degraded state. 229 private final boolean preferNonDegradedServer; 230 231 // The server ID of the server to which the request should be sent. 232 @NotNull private final String serverID; 233 234 235 236 /** 237 * Creates a new route to server request control with the provided 238 * information. 239 * 240 * @param isCritical Indicates whether this control should be 241 * considered critical. 242 * @param serverID The server ID for the server to which the 243 * request should be sent. It must not be 244 * {@code null}. 245 * @param allowAlternateServer Indicates whether the request may be 246 * routed to an alternate server in the 247 * event that the target server is not known, 248 * is not available, or is otherwise unsuited 249 * for use. If this has a value of 250 * {@code false} and the target server is 251 * unknown or unavailable, then the 252 * associated operation will be rejected. If 253 * this has a value of {@code true}, then an 254 * intermediate Directory Proxy Server may be 255 * allowed to route the request to a 256 * different server if deemed desirable or 257 * necessary. 258 * @param preferLocalServer Indicates whether the associated request 259 * may be routed to an alternate server if 260 * the target server is in a remote location 261 * and a suitable alternate server is 262 * available locally. This will only be used 263 * if {@code allowAlternateServer} is 264 * {@code true}. 265 * @param preferNonDegradedServer Indicates whether the associated request 266 * may be routed to an alternate server if 267 * the target server is in a degraded state 268 * and an alternate server is not in a 269 * degraded state. This will only be used if 270 * {@code allowAlternateServer} is 271 * {@code true}. 272 */ 273 public RouteToServerRequestControl(final boolean isCritical, 274 @NotNull final String serverID, 275 final boolean allowAlternateServer, 276 final boolean preferLocalServer, 277 final boolean preferNonDegradedServer) 278 { 279 super(ROUTE_TO_SERVER_REQUEST_OID, isCritical, 280 encodeValue(serverID, allowAlternateServer, preferLocalServer, 281 preferNonDegradedServer)); 282 283 this.serverID = serverID; 284 this.allowAlternateServer = allowAlternateServer; 285 this.preferLocalServer = (allowAlternateServer && preferLocalServer); 286 this.preferNonDegradedServer = 287 (allowAlternateServer && preferNonDegradedServer); 288 } 289 290 291 292 /** 293 * Creates a new route to server request control which is decoded from the 294 * provided generic control. 295 * 296 * @param control The generic control to be decoded as a route to server 297 * request control. 298 * 299 * @throws LDAPException If the provided control cannot be decoded as a 300 * route to server request control. 301 */ 302 public RouteToServerRequestControl(@NotNull final Control control) 303 throws LDAPException 304 { 305 super(control); 306 307 final ASN1OctetString value = control.getValue(); 308 if (value == null) 309 { 310 throw new LDAPException(ResultCode.DECODING_ERROR, 311 ERR_ROUTE_TO_SERVER_REQUEST_MISSING_VALUE.get()); 312 } 313 314 final ASN1Sequence valueSequence; 315 try 316 { 317 valueSequence = ASN1Sequence.decodeAsSequence(value.getValue()); 318 } 319 catch (final Exception e) 320 { 321 Debug.debugException(e); 322 throw new LDAPException(ResultCode.DECODING_ERROR, 323 ERR_ROUTE_TO_SERVER_REQUEST_VALUE_NOT_SEQUENCE.get( 324 StaticUtils.getExceptionMessage(e)), e); 325 } 326 327 try 328 { 329 final ASN1Element[] elements = valueSequence.elements(); 330 serverID = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 331 allowAlternateServer = 332 ASN1Boolean.decodeAsBoolean(elements[1]).booleanValue(); 333 334 boolean preferLocal = allowAlternateServer; 335 boolean preferNonDegraded = allowAlternateServer; 336 for (int i=2; i < elements.length; i++) 337 { 338 switch (elements[i].getType()) 339 { 340 case TYPE_PREFER_LOCAL_SERVER: 341 preferLocal = allowAlternateServer && 342 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 343 break; 344 case TYPE_PREFER_NON_DEGRADED_SERVER: 345 preferNonDegraded = allowAlternateServer && 346 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 347 break; 348 default: 349 throw new LDAPException(ResultCode.DECODING_ERROR, 350 ERR_ROUTE_TO_SERVER_REQUEST_INVALID_VALUE_TYPE.get( 351 StaticUtils.toHex(elements[i].getType()))); 352 } 353 } 354 355 preferLocalServer = preferLocal; 356 preferNonDegradedServer = preferNonDegraded; 357 } 358 catch (final LDAPException le) 359 { 360 Debug.debugException(le); 361 throw le; 362 } 363 catch (final Exception e) 364 { 365 Debug.debugException(e); 366 throw new LDAPException(ResultCode.DECODING_ERROR, 367 ERR_ROUTE_TO_SERVER_REQUEST_ERROR_PARSING_VALUE.get( 368 StaticUtils.getExceptionMessage(e)), e); 369 } 370 } 371 372 373 374 /** 375 * Encodes the provided information into a form suitable for use as the value 376 * of this control. 377 * 378 * @param serverID The server ID for the server to which the 379 * request should be sent. It must not be 380 * {@code null}. 381 * @param allowAlternateServer Indicates whether the request may be 382 * routed to an alternate server in the 383 * event that the target server is not known, 384 * is not available, or is otherwise unsuited 385 * for use. If this has a value of 386 * {@code false} and the target server is 387 * unknown or unavailable, then the 388 * associated operation will be rejected. If 389 * this has a value of {@code true}, then an 390 * intermediate Directory Proxy Server may be 391 * allowed to route the request to a 392 * different server if deemed desirable or 393 * necessary. 394 * @param preferLocalServer Indicates whether the associated request 395 * may be routed to an alternate server if 396 * the target server is in a remote location 397 * and a suitable alternate server is 398 * available locally. This will only be used 399 * if {@code allowAlternateServer} is 400 * {@code true}. 401 * @param preferNonDegradedServer Indicates whether the associated request 402 * may be routed to an alternate server if 403 * the target server is in a degraded state 404 * and an alternate server is not in a 405 * degraded state. This will only be used if 406 * {@code allowAlternateServer} is 407 * {@code true}. 408 * 409 * @return The encoded value for this control. 410 */ 411 @NotNull() 412 private static ASN1OctetString encodeValue(@NotNull final String serverID, 413 final boolean allowAlternateServer, 414 final boolean preferLocalServer, 415 final boolean preferNonDegradedServer) 416 { 417 Validator.ensureNotNull(serverID); 418 419 final ArrayList<ASN1Element> elements = new ArrayList<>(4); 420 elements.add(new ASN1OctetString(TYPE_SERVER_ID, serverID)); 421 elements.add( 422 new ASN1Boolean(TYPE_ALLOW_ALTERNATE_SERVER, allowAlternateServer)); 423 424 if (allowAlternateServer && (! preferLocalServer)) 425 { 426 elements.add(new ASN1Boolean(TYPE_PREFER_LOCAL_SERVER, false)); 427 } 428 429 if (allowAlternateServer && (! preferNonDegradedServer)) 430 { 431 elements.add(new ASN1Boolean(TYPE_PREFER_NON_DEGRADED_SERVER, false)); 432 } 433 434 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 435 } 436 437 438 439 /** 440 * Retrieves the server ID for the server to which the request should be sent. 441 * 442 * @return The server ID for the server to which the request should be sent. 443 */ 444 @NotNull() 445 public String getServerID() 446 { 447 return serverID; 448 } 449 450 451 452 /** 453 * Indicates whether the request may be routed to an alternate server if the 454 * target server is unknown, unavailable, or otherwise unsuited for use. 455 * 456 * @return {@code true} if the request may be routed to an alternate server 457 * if the target server is not suitable for use, or {@code false} if 458 * the operation should be rejected if it cannot be routed to the 459 * target server. 460 */ 461 public boolean allowAlternateServer() 462 { 463 return allowAlternateServer; 464 } 465 466 467 468 /** 469 * Indicates whether the request may be routed to an alternate server if the 470 * target server is nonlocal and a suitable server is available locally. This 471 * will only return {@code true} if {@link #allowAlternateServer} also returns 472 * {@code true}. 473 * 474 * @return {@code true} if the request may be routed to a suitable local 475 * server if the target server is nonlocal, or {@code false} if the 476 * nonlocal target server should still be used. 477 */ 478 public boolean preferLocalServer() 479 { 480 return preferLocalServer; 481 } 482 483 484 485 /** 486 * Indicates whether the request may be routed to an alternate server if the 487 * target server is in a degraded state and a suitable non-degraded server is 488 * available. This will only return {@code true} if 489 * {@link #allowAlternateServer} also returns {@code true}. 490 * 491 * @return {@code true} if the request may be routed to a suitable 492 * non-degraded server if the target server is degraded, or 493 * {@code false} if the degraded target server should still be used. 494 */ 495 public boolean preferNonDegradedServer() 496 { 497 return preferNonDegradedServer; 498 } 499 500 501 502 /** 503 * {@inheritDoc} 504 */ 505 @Override() 506 @NotNull() 507 public String getControlName() 508 { 509 return INFO_CONTROL_NAME_ROUTE_TO_SERVER_REQUEST.get(); 510 } 511 512 513 514 /** 515 * Retrieves a representation of this route to server request control as a 516 * JSON object. The JSON object uses the following fields: 517 * <UL> 518 * <LI> 519 * {@code oid} -- A mandatory string field whose value is the object 520 * identifier for this control. For the route to server request control, 521 * the OID is "1.3.6.1.4.1.30221.2.5.16". 522 * </LI> 523 * <LI> 524 * {@code control-name} -- An optional string field whose value is a 525 * human-readable name for this control. This field is only intended for 526 * descriptive purposes, and when decoding a control, the {@code oid} 527 * field should be used to identify the type of control. 528 * </LI> 529 * <LI> 530 * {@code criticality} -- A mandatory Boolean field used to indicate 531 * whether this control is considered critical. 532 * </LI> 533 * <LI> 534 * {@code value-base64} -- An optional string field whose value is a 535 * base64-encoded representation of the raw value for this route to server 536 * request control. Exactly one of the {@code value-base64} and 537 * {@code value-json} fields must be present. 538 * </LI> 539 * <LI> 540 * {@code value-json} -- An optional JSON object field whose value is a 541 * user-friendly representation of the value for this route to server 542 * request control. Exactly one of the {@code value-base64} and 543 * {@code value-json} fields must be present, and if the 544 * {@code value-json} field is used, then it will use the following 545 * fields: 546 * <UL> 547 * <LI> 548 * {@code server-id} -- A mandatory string field whose value is the 549 * server ID for the server to which the request should be sent. 550 * </LI> 551 * <LI> 552 * {@code allow-alternate-server} -- A mandatory Boolean field that 553 * indicates whether the Directory Proxy Server may choose to use a 554 * different server than the one requested if the requested server is 555 * not known or is not available. 556 * </LI> 557 * <LI> 558 * {@code prefer-local-server} -- An optional Boolean field that 559 * indicates whether the request may be routed to an alternative 560 * server if the requested server is not in the same location as the 561 * Directory Proxy Server. 562 * </LI> 563 * <LI> 564 * {@code prefer-non-degraded-server} -- An optional Boolean field 565 * that indicates whether the request may be routed to an alternative 566 * server if the requested server is in a degraded state. 567 * </LI> 568 * </UL> 569 * </LI> 570 * </UL> 571 * 572 * @return A JSON object that contains a representation of this control. 573 */ 574 @Override() 575 @NotNull() 576 public JSONObject toJSONControl() 577 { 578 final Map<String,JSONValue> valueFields = new LinkedHashMap<>(); 579 valueFields.put(JSON_FIELD_SERVER_ID, new JSONString(serverID)); 580 valueFields.put(JSON_FIELD_ALLOW_ALTERNATE_SERVER, 581 new JSONBoolean(allowAlternateServer)); 582 583 if (allowAlternateServer) 584 { 585 valueFields.put(JSON_FIELD_PREFER_LOCAL_SERVER, 586 new JSONBoolean(preferLocalServer)); 587 valueFields.put(JSON_FIELD_PREFER_NON_DEGRADED_SERVER, 588 new JSONBoolean(preferNonDegradedServer)); 589 } 590 591 return new JSONObject( 592 new JSONField(JSONControlDecodeHelper.JSON_FIELD_OID, 593 ROUTE_TO_SERVER_REQUEST_OID), 594 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME, 595 INFO_CONTROL_NAME_ROUTE_TO_SERVER_REQUEST.get()), 596 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY, 597 isCritical()), 598 new JSONField(JSONControlDecodeHelper.JSON_FIELD_VALUE_JSON, 599 new JSONObject(valueFields))); 600 } 601 602 603 604 /** 605 * Attempts to decode the provided object as a JSON representation of a 606 * route to server request control. 607 * 608 * @param controlObject The JSON object to be decoded. It must not be 609 * {@code null}. 610 * @param strict Indicates whether to use strict mode when decoding 611 * the provided JSON object. If this is {@code true}, 612 * then this method will throw an exception if the 613 * provided JSON object contains any unrecognized 614 * fields. If this is {@code false}, then unrecognized 615 * fields will be ignored. 616 * 617 * @return The route to server request control that was decoded from 618 * the provided JSON object. 619 * 620 * @throws LDAPException If the provided JSON object cannot be parsed as a 621 * valid route to server request control. 622 */ 623 @NotNull() 624 public static RouteToServerRequestControl decodeJSONControl( 625 @NotNull final JSONObject controlObject, 626 final boolean strict) 627 throws LDAPException 628 { 629 final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper( 630 controlObject, strict, true, true); 631 632 final ASN1OctetString rawValue = jsonControl.getRawValue(); 633 if (rawValue != null) 634 { 635 return new RouteToServerRequestControl(new Control( 636 jsonControl.getOID(), jsonControl.getCriticality(), rawValue)); 637 } 638 639 640 final JSONObject valueObject = jsonControl.getValueObject(); 641 642 final String serverID = valueObject.getFieldAsString(JSON_FIELD_SERVER_ID); 643 if (serverID == null) 644 { 645 throw new LDAPException(ResultCode.DECODING_ERROR, 646 ERR_ROUTE_TO_SERVER_REQUEST_JSON_MISSING_FIELD.get( 647 controlObject.toSingleLineString(), JSON_FIELD_SERVER_ID)); 648 } 649 650 final Boolean allowAlternateServer = 651 valueObject.getFieldAsBoolean(JSON_FIELD_ALLOW_ALTERNATE_SERVER); 652 if (allowAlternateServer == null) 653 { 654 throw new LDAPException(ResultCode.DECODING_ERROR, 655 ERR_ROUTE_TO_SERVER_REQUEST_JSON_MISSING_FIELD.get( 656 controlObject.toSingleLineString(), 657 JSON_FIELD_ALLOW_ALTERNATE_SERVER)); 658 } 659 660 Boolean preferLocalServer = 661 valueObject.getFieldAsBoolean(JSON_FIELD_PREFER_LOCAL_SERVER); 662 if (preferLocalServer == null) 663 { 664 preferLocalServer = true; 665 } 666 667 Boolean preferNonDegradedServer = 668 valueObject.getFieldAsBoolean(JSON_FIELD_PREFER_NON_DEGRADED_SERVER); 669 if (preferNonDegradedServer == null) 670 { 671 preferNonDegradedServer = true; 672 } 673 674 675 if (strict) 676 { 677 final List<String> unrecognizedFields = 678 JSONControlDecodeHelper.getControlObjectUnexpectedFields( 679 valueObject, JSON_FIELD_SERVER_ID, 680 JSON_FIELD_ALLOW_ALTERNATE_SERVER, 681 JSON_FIELD_PREFER_LOCAL_SERVER, 682 JSON_FIELD_PREFER_NON_DEGRADED_SERVER); 683 if (! unrecognizedFields.isEmpty()) 684 { 685 throw new LDAPException(ResultCode.DECODING_ERROR, 686 ERR_ROUTE_TO_SERVER_REQUEST_JSON_UNRECOGNIZED_FIELD.get( 687 controlObject.toSingleLineString(), 688 unrecognizedFields.get(0))); 689 } 690 } 691 692 693 return new RouteToServerRequestControl(jsonControl.getCriticality(), 694 serverID, allowAlternateServer, preferLocalServer, 695 preferNonDegradedServer); 696 } 697 698 699 700 /** 701 * {@inheritDoc} 702 */ 703 @Override() 704 public void toString(@NotNull final StringBuilder buffer) 705 { 706 buffer.append("RouteToServerRequestControl(isCritical="); 707 buffer.append(isCritical()); 708 buffer.append(", serverID='"); 709 buffer.append(serverID); 710 buffer.append("', allowAlternateServer="); 711 buffer.append(allowAlternateServer); 712 buffer.append(", preferLocalServer="); 713 buffer.append(preferLocalServer); 714 buffer.append(", preferNonDegradedServer="); 715 buffer.append(preferNonDegradedServer); 716 buffer.append(')'); 717 } 718}